#102 Data visualization: the hard part

One thing I was really looking forward to building for parlementrics was the data visualization piece. I just love it when data “speaks to me” through intuitive visualizations. Until now, however, I had never worked on a project that allowed me to embrace that idea myself. So, I dove into the task with gusto. But I soon realized that creating great data visualizations is much harder than it looks. In fact, the opposite is true. Great data visualizations make complex stuff look easy! ...

April 27, 2026

#101 Transparency builds trust

Here’s one aspect of conscientious AI use that is often overlooked: Transparency. Users have a right to know if the information they’re viewing was created—or at least curated—by a human being or an algorithm. In the EU, this right is enshrined in the AI Act, albeit not in a strict manner. According to the Act, companies must inform users when they are interacting with an AI system unless it is obvious. Additionally, AI systems that generate synthetic content, such as deepfakes, must mark their outputs as artificially generated. ...

April 21, 2026

#58 The occasional toast can’t hurt

Some of the designers and frontend devs I’ve worked with may remember my rants against toast notifications: “Why do I need a success message for every action? I expect things to work. Only tell me when something breaks.” But… I’ll admit it: Sometimes toasts do have their merit. Two examples from poketto.me: 🔹 Copy to clipboard (Podcast feed URL): When users click the “copy” button, the action happens instantly. But without any feedback, it feels… awkward. ...

August 27, 2025

#55 UX details sometimes make all the difference

In WebSockets: More than tech vanity, I talked about how poketto.me uses WebSockets to keep the UI in sync with async backend processes—like translating, TTS, etc. Neat? Sure. Game-changing? Probably not. Just like I asked about AI in AI is not a value proposition: where would you put that on the Business Model Canvas? It doesn’t really fit as a Value Proposition, does it? But that doesn’t mean it’s not important. Take Strava, for example. ...

August 24, 2025

#51 WebSockets: More than tech vanity

As I said in Socket science isn’t rocket science, WebSockets are quite easy to use with Python + Flask + Socket.IO on the backend and Angular + Socket.IO + RxJS on the frontend. But why bother? Dealing with asynchronous requests is more of a hassle than not. And for a “boring” app like poketto.me, aren’t synchronous HTTP requests/responses good enough? Here are two use cases where, despite the app’s apparent simplicity, asynchronous backend/frontend communication adds real value: ...

August 20, 2025

#38 Consistency Beats Accuracy (Part 1)

As I add more UI-heavy functionality to poketto.me (not all of it public yet), I keep running into the same issue: it’s tempting — but risky — to constantly invent new UI patterns and elements. Case in point: On the Saves page, each saved item has a “more” menu with actions like Archive, Delete, or Edit Tags. But when I worked on the News Feed, I completely overlooked this. Instead, I gave each news item its own action bar — dedicated buttons to save the item or, once saved, edit its tags. (See Exhibit A.) ...

August 7, 2025

#18 Socket science isn’t rocket science! 🚀 Or: WebSockets + Flask + SocketIO = ❤️

For some reason, async communication between a web app backend and the browser causes more anxiety than it should (guilty 🙋). I’ve had my fair share of headaches with WebSocket frameworks before, but for poketto.me, I tried a much simpler stack—and was pleasantly surprised: ➡️http backend: Flask ( https://flask.palletsprojects.com/en/stable/) ➡️websocket backend: Flask-Socketio ( https://flask-socketio.readthedocs.io/en/latest/) ➡️websocket frontend: socketio-client ( https://www.npmjs.com/package/socket.io-client) 🔌 Backend: Handling connections is dead simple @socketio.on('connect') def handle_connect(): _, user_id = authenticate() sid = request.sid connected_clients[user_id] = sid 📤 Sending data to a connected client sid = connected_clients.get(user_id)\ if sid: socketio.emit('message', { 'message_type': 'save_changed', 'data': { 'id': save_id, 'state': 'archived' } }, to=sid) #### **🖥️ Frontend: Receiving messages is just as easy** const socket = io(environment.WS_BASE_URL, { ...

July 18, 2025