Speeding up the image playground

September 2026

The Image Playground shows six cards, and each one asks the server for a picture. ImageMagick drew every one of those pictures from scratch on every page load, all six at the same time, so it took six or seven seconds before the page filled in.

One effect made it worse. Text Wave prints a random word on its image, and it got that word from a free word API hosted on Heroku, on every request. When the API was slow, the image waited on it for up to two seconds. The code already had a list of backup words for when the API failed, so I dropped the API call and used the list.

The bigger fix was caching. Each image comes from an effect name and a seed number, and the same pair always draws the same picture. Now the server saves each image it draws to a cache folder, named after the effect and seed, and sends that saved file the next time someone asks for the same pair. The first visitor to a new seed still waits. The six default cards always use the same seeds, though, so after that the page loads in under two seconds. The effect name ends up in a file path now, so I also made the script check it against the six effect names before using it.

The cache broke once without me noticing. PHP on my server runs as a different user than I do, so the cache folder has to be writable by that user. I set that up when I added the cache, but a later upload of the whole site reset the folder's permissions, and PHP stopped saving new images. Nothing looked wrong, because the six default images were already saved. I found it while checking the server before another upload. Now I only upload the files that changed.

While writing this I noticed Text Wave had no word on it at all. The script only drew the word if a certain font folder existed, and that folder isn't on my server. The font it uses sits in the same folder as the script, so I pointed the check at that file instead.

After that, most of the wait was the download, because the six images added up to about 4 MB of PNG. Saving them as WebP instead brought that down to about 0.7 MB, and at the size the cards show them I can't tell the difference. With the images cached, the page now loads in under a second.

← All notes