#17 Designing for mobile after the fact is painful

I’ll admit it: when I built the frontend for [poketto.me, I focused mostly on desktop browsers—except for the reading experience, which was always meant to be mobile-first. But optimizing the rest of the UI for smaller screens later on? A real hassle—and one that could’ve been avoided had I truly embraced mobile-first design from the start. Here are a few key lessons the hard way taught me: 📱 *Thumb-friendly design matters* The Rule of Thumbs is real: ...

July 17, 2025

#16 Material’s tooltip interferes with touch-scrolling on mobile

As I mentioned the other day, I love Angular Material. However, I was quite surprised to discover that the matTooltip directive can negatively impact the user experience on mobile 🤯 I noticed that users couldn’t 'drag to scroll' on poketto.me on their phones (in both the Android app and the browser) when they started to drag particular elements on the screen, such as the save title images. After a lot of analysis and debugging, I discovered that the matTooltip directive, which I use to render tooltips displaying the full save title in case it is abbreviated, sets touch-action: none; on that element. This means: On a mobile device, users can't start scrolling the page with that element as an anchor. It feels totally weird! ...

July 16, 2025

#15 Cloud Build beats GitLab CI for my use case.

When I set up my personal blog, ralphpmayr.com, years ago, I opted for a GitLab CI pipeline to build and deploy it. However, for poketto.me, I was looking for something faster, cheaper and more closely integrated with the Google Cloud ecosystem. I opted for Google's own CloudBuild and discovered that it integrates seamlessly with GitLab.com. In GitLab, all you need to do is create two API keys (one for read access and one for edit access), configure these in Google Cloud and CloudBuild will then be able to fetch and build any GitLab project. ...

July 15, 2025

#14 The process to get an app into Google Play is… byzantine

🏗️First, of course, you actually got to build your app. Then you register at the Google Play Console (and fork over $25). Then you provide your name, contact details, etc. and then the fun starts: You need official ID (drivers license, passport), proof of residence (“Meldezettel” in Austria), proof that you own an Android device, install the Google Play Console App on that device, and verify your contact phone number. ...

July 14, 2025

#13 "Token used too early" — the weirdest Google Sign-In error.

I’ve had my ups and downs with “Sign in with Google”: ⬆️It’s simple and works well on the web ⬇️It’s a complete hassle inside a hosted WebView in a native mobile app But here’s something really funny: I local clock is ahead of Google's — sometimes by as little as a few milliseconds – the sign in call will fail with “Token used too early.” 🤯 ✅ Solution: resync your system clock (in my case, my MacBook with Apple's time server). ...

July 13, 2025

#12 WebView ↔ Native app communication is easier than you think.

Even without relying on the utilities provided by Capacitor, you can easily pass data back and forth between your web app and its native counterpart: ➡️In JavaScript / TypeScript you can register global functions on the window object. The native code can call these via executeJavaScript() on the WebView. ➡️In the other direction, the native code can register a JavaScript interface on the WebView: webView.addJavascriptInterface(new Object() { @JavascriptInterface public void onSessionId(String value) { SaveUrlHandler.instance.setSessionId(value); } @JavascriptInterface public void closeApp() { MainActivity.this.finish(); } }, "Android"); which the JavaScript / TypeScript code can call whenever it wants: ...

July 12, 2025

#10 Running text-to-speech in the #Cloud is harder than you would think (part three)

So, after finally setting up a dedicated virtual machine (VM) to run my text-to-speech workloads and wiring up all the build and deployment scripts, I got a bit excited. Could I reduce the TTS latency even further if the VM had GPU power? In theory: Yes. In practice: Google doesn't give you access to their GPUs straight away. There’s a special quota setting for VM instances with GPUs, and by default that’s set to zero. As a regular user, you cannot increase this without contacting Google Cloud Support. ...

July 10, 2025

#9 Running text-to-speech in the #Cloud is harder than you would think (part two)

Do you remember when I mentioned the difficulty of running 🐸 CoquiTTS in the cloud yesterday? My first experiment was to run it directly in my Cloud Run backend service. In theory, this could have worked, but you'll never guess why it failed in practice. x86 CPUs. Really. Like the ones we had in our computers in the 90s. How did I figure this out? After taking a horribly long time to start up, the TTS service failed with a message saying that it was running on an 'incompatible' CPU architecture. Specifically, 32-bit x86 CPUs. ...

July 9, 2025

#8 Running text-to-speech in the #Cloud is harder than you would think (part one)

For the podcast automation feature that I’m planning for a future version of poketto.me, I’ve been experimenting with various text-to-speech solutions. The easiest and highest-quality approach would have been the ElevenLabs API. However, considering the “throwaway” nature of these audio files – most of which would only be listened to once by one person – and the cost structure that this would introduce, I desperately need a cheaper approach. The Python library 🐸 CoquiTTS is pretty awesome: There are many different models to choose from, ranging from 'super low latency' to 'high quality' (including voice cloning). Therefore, poketto.me users could choose from many different voices, and from a commercial perspective, I could set different price points for different levels of quality and latency. However, they all require significant computing power to function. ...

July 8, 2025

#7 Refactoring “legacy” code? Let the AI handle it!

For reasons outlined in yesterday's post, I had to switch poketto.me from #CloudSQL (MySQL) to a completely different database architecture: Firebase 🔥 At that stage, the Python backend code base wasn’t huge, but it was already fairly substantial. It included CRUD operations for several entities, as well as some basic lookup logic. Rewriting the whole thing would have taken me at least half a day. Instead, I asked my good friend #Claude to take care of things. And, to my surprise, the result worked straight away! 🎁The “dorp in” replacement generated by the AI immediately passed my unit tests, and also the chatbot’s instructions for how to set up and configure #Firebase were actually useful. ...

July 7, 2025