The Scrape Escape

I hope you had a lovely weekend filled with some great coffee. Mine was a bit less lovely, because I spent a good chunk of it learning just how many websites now block scraping and crawling thanks to the flood of AI bots.

This matters for Coffee Management, because when you paste a coffee URL into Visualizer and ask it to import the details with AI, I want that to work as often as possible.

With the new changes the scraper still tries the old, simple approach first. But when that fails, Visualizer now falls back to Crawlbase, which can fetch the page through a real browser. That is much more reliable for blocked sites, but it can also take much longer. This longer runtime broke the existing approach I had, because the request would time out. So I was forced into switching the whole approach by using websockets via Action Cable.

The good news is that this actually made the whole feature much better. Instead of quietly doing mysterious things in the background while you watch the little animated logo, Visualizer now tells you exactly what it is working on. You can see it step through fetching the page, retrying in browser mode if needed, extracting the useful bits, and finally applying the results.

Another nice quality of life improvement: the PWA, when you save Visualizer to your phone home screen, now supports pull to refresh on the shot list. Small thing, but very handy if you use Visualizer on your phone and want that app-like feel.

I also spent some time rewriting the homepage and Premium messaging. No new features there, but I wanted the site to better reflect what Visualizer actually is: a place to keep useful coffee data in one place, learn from it, and brew better coffee because of it.

As always, if you run into bugs or have ideas for improvements, please keep opening GitHub issues. I really do read them all, and they very often end up shipped. And if you want all the nitty gritty details, here is the full diff.

Thanks for reading, and have a great week ahead! ☕


Feeling Bitter, Looking Better

There is a new chart option inspired by this GitHub issue about showing temperature together with the other curves: if you want to see temperature overlaid on the main chart instead of split out on its own, you can now enable that in your profile settings. The separate temperature chart remains the default, but I know some of you prefer having everything in one place.

I also added bitterness to tasting assessments, following some very sensible observations on the scoring metrics. Leaving it out felt more and more silly the longer I looked at it. That gives you 8 dimensions total and makes the whole thing feel more complete and balanced.

Then there was a request to also copy taste rating and coffee grams when copying from previous shots. After the initial straightforward implementation, I got a few reports about drink weight changing when copying values from another shot and drink weight being overwritten during copy, so I refined the whole thing a bit more. Rollbacks are clearer now, and imported shot weights should no longer get accidentally overwritten when copying details from another shot.

There were several API and security improvements too. Private notes are now available via the API, the API authentication is properly stateless now, and the docs mention rate limits and response formats much more clearly. If you want all the nitty gritty details, here is the full diff.

As always, if you run into bugs or have ideas for improvements, please keep opening GitHub issues.

Thanks for reading, and have a great week! ☕


Tasting Assessments

If you are a Premium user, you can now add tasting assessment fields to your shots. This gives you a structured way to capture the sensory side of a shot instead of leaving everything buried in freeform notes.

I did not want to invent some random scoring system here, so this is based on the modern SCA CVA Descriptive direction, also known as the new SCA cupping form. Specifically, you can assess a shot across 7 dimensions: fragrance, aroma, flavor, aftertaste, acidity, sweetness, and mouthfeel. Each one is rated on a 0 to 15 intensity scale, based on the official descriptive assessment.

Those fields then show up visually on the shot page and comparison page, so you can get a quick feel for how two shots differ without having to read through everything line by line. I am quite excited about this one because I have wanted to render a taste “spider web chart” for a long time, but it took me quite a while to end up at a solution I actually liked.

There were some other nice improvements as well. I fixed a long standing annoyance where zoomed charts had broken hover behavior, so chart exploration should now feel smoother. I also fixed a few user reported issues: some GaggiMate files inconsistently using the wrong flow source, Loffee Labs bean search no longer returning results, and broken Gaggiuino timestamps sending shots back to 1970. If you run into bugs, or just have ideas for improvements, please keep opening GitHub issues. I really do read them all, and they most often end up shipped.

Behind the scenes, I also started self hosting the API docs and finished moving all storage away from Amazon to Cloudflare. I had already moved avatars away from Cloudinary a while back, and now everything else is on Cloudflare too. So Visualizer is now completely de-Amazoned. ☁️

As always, there were many smaller fixes and polish updates too, including some UI cleanup, better headings, sticky coffee bag edit titles, and a few Loffee Labs improvements.

Thanks for reading, and enjoy what’s left of the weekend! ☕