All Articles
Remembering What the AI Decided: Four Marks in the Cache Key Paid Off on Model-Swap Day
A small on-device cache for AI answers, with the model name and prompt version in the key so old answers vanish on swap day. TypeScript plus simulated results.
You Changed the Environment Variable and Rebuilt for Android, but the App Still Points at the Old Server. Look at the Line That Says UP-TO-DATE
Change only an EXPO_PUBLIC_ value and rebuild a release for Android, and the bundle task can be skipped as UP-TO-DATE, leaving the old value inside. I reproduce the same behavior in a minimal Gradle project and cover how to spot it and what to do until it is fixed.
Sending temperature to the Claude API Now Returns a 400 on the New Version. Finding Every Spot in Your App
Claude API version 2026-10-21 returns a 400 if you send temperature, top_p or top_k. When it hits you, a script to scan your app and SDK setup, and the order to fix things in.
Your EAS Update Opens in Expo Go on iPhone but Stops on Android with "Failed to download remote update". The 403 You Get Even When Signed In
An EAS Update that opens in Expo Go on iOS but stops on Android (SDK 57) with Failed to download remote update. The cause is a sign-in token saved in one place and read from another, and the fix sits on the SDK 58 side. The order to check things in, and what to run yourself.
Your 5% Rollout Says 99.76% Crash-Free. How Many Users Until You Can Trust It?
At 5% rollout, a crash-free rate rests on few users and the interval is wide. A Wilson-interval script that says proceed, wait or halt, plus simulated numbers on how often you halt a good release.
The Night Before You Submit: Which Dependencies to Check First, in Five Steps Anyone Can Follow
Upgrading every library the night before submission is how crashes that only hit old devices slip into a release. Here is the order I settled on in my own wallpaper apps: check what the stores decide first, and write down what you chose not to upgrade.
Linking.canOpenURL Keeps Returning false on iOS Only — Declaring LSApplicationQueriesSchemes, and the 25-Entry Cap Coming With iOS 27
When Linking.canOpenURL returns false on iOS no matter what is installed, the cause is usually a missing Info.plist declaration. Here is how to fix it in Expo's app.json, what Android needs instead, and how to prepare for the 25-entry limit for apps linked on iOS 27.
Fullscreen Ads Stopped Showing After Going Back and Forth Between Screens — The Ad Holder Was Still Holding a Closed Screen
Fullscreen ads vanished after reopening a screen because a reused ad holder kept notifying a closed screen. A holder that swaps only its listener target, tested in Node.
It Looks Opaque, but App Store Connect Says the Icon Has an Alpha Channel — Checking the PNG Before You Upload
ITMS-90717 (Invalid large app icon) can fire on an icon that shows no transparency at all, because an alpha channel is enough. I built six sample PNGs to tell the cases apart, and share a stdlib-only checker and a flatten step.
Sound Effects Stop at Play #40 — With expo-audio's createAudioPlayer, remove() Alone Isn't Cleanup
Creating a createAudioPlayer instance per play in expo-audio can leave Android silent after about 40 plays, with didJustFinish never arriving. What remove() and release() each do, three ways to restructure, and how to notice when it happens.
Is Your Rork App Still Calling Sonnet 4.5? Finding Out Before November 30
Claude Sonnet 4.5 is scheduled to retire from the API on November 30, 2026. A small script to find leftover model IDs in your app, and the order to fix them in depending on where they live.
The ANR Was Coming From Cleanup When a Screen Closed: Classifying the Blocking Line From Traces
A Python script that reads Android ANR traces and classifies the line that blocked the main thread, such as billing client teardown or synchronous image decoding. Two causes I found in my wallpaper apps, and the thinking behind the fixes.