<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Kini Insight</title>
    <link>https://www.kiniinsight.com/en/</link>
    <description>Notes from building mobile apps - the parts that broke, what the fix actually was, and the tools behind it. Written from what I ran, not from memory.</description>
    <language>en</language>
    <atom:link href="https://www.kiniinsight.com/en/rss.xml" rel="self" type="application/rss+xml" />
    <lastBuildDate>Mon, 24 Aug 2026 00:00:00 GMT</lastBuildDate>
    <item>
      <title>A funnel with every screen logged, and no idea where users left</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-24-we-logged-every-screen-and-still-could-not-say-where-users-left/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-24-we-logged-every-screen-and-still-could-not-say-where-users-left/</guid>
      <pubDate>Mon, 24 Aug 2026 00:00:00 GMT</pubDate>
      <description>Screen tracking was firing, yet the funnel question stayed unanswerable. The data landed where I could not query it, and one step I added would read 100% forever.</description>
      <category>funnel</category>
      <category>analytics</category>
      <category>Mixpanel</category>
      <category>Firebase Analytics</category>
      <category>instrumentation</category>
    </item>
    <item>
      <title>One line changed and git recorded 295</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-21-one-line-changed-and-git-recorded-295/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-21-one-line-changed-and-git-recorded-295/</guid>
      <pubDate>Fri, 21 Aug 2026 00:00:00 GMT</pubDate>
      <description>When line endings flip from LF to CRLF, git treats every line as modified. Measured numbers for the diff, the blame damage, and why -w beats --ignore-rev.</description>
      <category>git</category>
      <category>CRLF</category>
      <category>line endings</category>
      <category>gitattributes</category>
      <category>code review</category>
    </item>
    <item>
      <title>Wiring subscriptions: a full Play Store checklist</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-21-wiring-subscriptions-the-full-play-store-and-revenuecat-checklist/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-21-wiring-subscriptions-the-full-play-store-and-revenuecat-checklist/</guid>
      <pubDate>Fri, 21 Aug 2026 00:00:00 GMT</pubDate>
      <description>Every step of attaching subscriptions to an Android app, in order, with the specific places it silently breaks and how to tell which layer failed.</description>
      <category>subscriptions</category>
      <category>in-app purchases</category>
      <category>RevenueCat</category>
      <category>Google Play</category>
      <category>Android</category>
    </item>
    <item>
      <title>Most of the work in shipping in-app subscriptions was not code</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-20-most-of-the-work-in-shipping-in-app-subscriptions-was-not-code/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-20-most-of-the-work-in-shipping-in-app-subscriptions-was-not-code/</guid>
      <pubDate>Thu, 20 Aug 2026 00:00:00 GMT</pubDate>
      <description>Wiring in-app subscriptions blocked three releases in one day. Every blocker was a name or a scope that had to match across two systems, and none of them errored.</description>
      <category>in-app subscriptions</category>
      <category>RevenueCat</category>
      <category>Google Play</category>
      <category>Android permissions</category>
      <category>Firestore</category>
    </item>
    <item>
      <title>What makes an LLM call cacheable is not temperature</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-19-what-makes-an-llm-call-cacheable-is-not-temperature/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-19-what-makes-an-llm-call-cacheable-is-not-temperature/</guid>
      <pubDate>Wed, 19 Aug 2026 00:00:00 GMT</pubDate>
      <description>Caching an LLM call looked trivial until I checked why it was safe. The reason I reached for first was wrong, and partial hits corrupted the totals.</description>
      <category>LLM</category>
      <category>caching</category>
      <category>API cost</category>
      <category>Firestore</category>
      <category>system design</category>
    </item>
    <item>
      <title>The design tokens existed. The code just did not use them</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-18-the-design-tokens-existed-the-code-just-did-not-use-them/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-18-the-design-tokens-existed-the-code-just-did-not-use-them/</guid>
      <pubDate>Tue, 18 Aug 2026 00:00:00 GMT</pubDate>
      <description>An app with design tokens still had 953 hardcoded colors, and 349 of them were values the tokens already defined. Automating the swap went wrong twice.</description>
      <category>design tokens</category>
      <category>design systems</category>
      <category>refactoring</category>
      <category>codemod</category>
      <category>react-native</category>
    </item>
    <item>
      <title>uniq Says Two Different Korean Lines Are Duplicates</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-17-uniq-says-two-different-korean-lines-are-duplicates/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-17-uniq-says-two-different-korean-lines-are-duplicates/</guid>
      <pubDate>Mon, 17 Aug 2026 00:00:00 GMT</pubDate>
      <description>On macOS, uniq reports duplicates that do not exist in non-Latin text. It collapsed 397 distinct lines into one. The cause is collation, and uniq never signals it.</description>
      <category>uniq</category>
      <category>shell</category>
      <category>unicode</category>
      <category>locale</category>
      <category>macos</category>
    </item>
    <item>
      <title>What people searching for morning routines actually ask about</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-17-what-people-searching-for-the-miracle-morning-actually-ask/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-17-what-people-searching-for-the-miracle-morning-actually-ask/</guid>
      <pubDate>Mon, 17 Aug 2026 00:00:00 GMT</pubDate>
      <description>I measured 40 morning routine autocomplete suggestions. Eight ask about side effects and failure, and the real question underneath is whether sleeping less is fine.</description>
      <category>morning routine</category>
      <category>sleep</category>
      <category>habits</category>
      <category>search data</category>
      <category>self improvement</category>
    </item>
    <item>
      <title>Android widgets: a working preview does not mean a working widget</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-16-a-working-widget-preview-does-not-mean-a-working-widget/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-16-a-working-widget-preview-does-not-mean-a-working-widget/</guid>
      <pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate>
      <description>I shipped the same broken Android widget four times. The preview looked right and the build passed, but adding it to the home screen failed every time.</description>
      <category>Android</category>
      <category>widgets</category>
      <category>RemoteViews</category>
      <category>app development</category>
      <category>debugging</category>
    </item>
    <item>
      <title>People who keep breaking habits are already counting the tries</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-16-people-searching-for-repeated-failure-are-already-counting/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-16-people-searching-for-repeated-failure-are-already-counting/</guid>
      <pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate>
      <description>I measured 36 autocomplete suggestions for a Korean phrase about broken habits. Three ask how to fix it. Five assume it already happened again.</description>
      <category>habits</category>
      <category>search data</category>
      <category>product copy</category>
      <category>motivation</category>
      <category>app development</category>
    </item>
    <item>
      <title>Four of my five keywords died on search intent</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-15-four-of-five-keywords-died-on-intent/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-15-four-of-five-keywords-died-on-intent/</guid>
      <pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate>
      <description>I picked five topics by search volume and dropped four an hour later. Reading the ranking pages showed the search intent behind those words was different.</description>
      <category>search intent</category>
      <category>SEO</category>
      <category>keyword research</category>
      <category>content strategy</category>
      <category>blogging</category>
    </item>
    <item>
      <title>My TypeScript check was silent, not passing</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-15-my-type-check-was-silent-not-passing/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-15-my-type-check-was-silent-not-passing/</guid>
      <pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate>
      <description>I judged TypeScript by grepping tsc output for a string it never prints. It stayed silent every time, and I read silence as success. Six real errors were hiding.</description>
      <category>typescript</category>
      <category>tsc</category>
      <category>CI</category>
      <category>shell</category>
      <category>verification</category>
    </item>
    <item>
      <title>Searching for a study planner returns three different things</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-15-study-planner-means-three-different-things/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-15-study-planner-means-three-different-things/</guid>
      <pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate>
      <description>The phrase study planner returns a consultant, a paper notebook, and an app in one page of results. Decide which you want, or you buy whichever had the best ad.</description>
      <category>study planner</category>
      <category>study planning</category>
      <category>planner comparison</category>
      <category>self management</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The Firestore index deployed and the error stayed</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-15-the-index-deployed-and-the-error-stayed/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-15-the-index-deployed-and-the-error-stayed/</guid>
      <pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate>
      <description>I deployed a Firestore index, relaunched, and got the identical failed-precondition error. The deploy was fine. A building index reports exactly like a missing one.</description>
      <category>firestore index</category>
      <category>firebase</category>
      <category>failed-precondition</category>
      <category>deployment</category>
      <category>composite index</category>
    </item>
    <item>
      <title>Turning off the auto popup removed the only entry point</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-15-turning-off-the-auto-popup-deleted-the-feature/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-15-turning-off-the-auto-popup-deleted-the-feature/</guid>
      <pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate>
      <description>I disabled a bottom sheet that opened automatically because it annoyed me. That automatic open was its only entry point. I did the same thing twice in two days.</description>
      <category>entry point</category>
      <category>react native</category>
      <category>refactoring</category>
      <category>dead code</category>
      <category>product</category>
    </item>
    <item>
      <title>I added voice input for todos because planning was tedious</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-15-voice-input-because-planning-was-tedious/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-15-voice-input-because-planning-was-tedious/</guid>
      <pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate>
      <description>Typing todos into my own app annoyed me, so I built voice input for one spoken sentence. No model, just regex, and a split rule that nearly cut verbs in half.</description>
      <category>voice input</category>
      <category>korean parsing</category>
      <category>on-device stt</category>
      <category>regex</category>
      <category>product</category>
    </item>
    <item>
      <title>The JS ran at 60fps and the screen stayed black</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-13-view-flattening-killed-the-gl-context/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-13-view-flattening-killed-the-gl-context/</guid>
      <pubDate>Thu, 13 Aug 2026 00:00:00 GMT</pubDate>
      <description>A 3D planet stopped animating on iPhone only. The GL context was alive, three.js rendered every frame, and endFrameEXP fired 60 times a second. Nothing reached the screen. The cause was React Native&apos;s view flattening.</description>
      <category>react-native</category>
      <category>new architecture</category>
      <category>fabric</category>
      <category>expo-gl</category>
      <category>view flattening</category>
      <category>three.js</category>
      <category>ios</category>
    </item>
    <item>
      <title>Your CLAUDE.md rules disappear on the next machine</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-11-claude-md-rules-vanish-on-another-machine/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-11-claude-md-rules-vanish-on-another-machine/</guid>
      <pubDate>Tue, 11 Aug 2026 00:00:00 GMT</pubDate>
      <description>Instruction files fail open. Auditing CLAUDE.md turned up two rules living only on this laptop, plus two referenced files that never existed.</description>
      <category>CLAUDE.md</category>
      <category>AI coding tools</category>
      <category>monorepo</category>
      <category>developer environment</category>
      <category>reproducibility</category>
      <category>automation</category>
      <category>code review</category>
    </item>
    <item>
      <title>GLB file size: 99% of mine was textures the app threw away</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-11-glb-file-size-textures/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-11-glb-file-size-textures/</guid>
      <pubDate>Tue, 11 Aug 2026 00:00:00 GMT</pubDate>
      <description>Two sky models arrived at 8MB for a phone app. Almost all of that GLB file size was 2048px textures my renderer discards before the first frame.</description>
      <category>GLB file size</category>
      <category>gltf</category>
      <category>three.js</category>
      <category>react-three-fiber</category>
      <category>react native 3d</category>
      <category>asset optimization</category>
    </item>
    <item>
      <title>Habit streaks punish the people who are best at them</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-11-habit-streaks-removed/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-11-habit-streaks-removed/</guid>
      <pubDate>Tue, 11 Aug 2026 00:00:00 GMT</pubDate>
      <description>Habit streaks get heavier the longer they run: one missed day costs 3 early on and 100 later. Here is what I shipped instead, with numbers.</description>
      <category>habit streaks</category>
      <category>habit tracker</category>
      <category>product design</category>
      <category>motivation</category>
      <category>retention</category>
      <category>app design</category>
    </item>
    <item>
      <title>A React Native Modal always wins: the new-user soft lock</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-11-react-native-modal-soft-lock/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-11-react-native-modal-soft-lock/</guid>
      <pubDate>Tue, 11 Aug 2026 00:00:00 GMT</pubDate>
      <description>The onboarding button did nothing and the app looked frozen. A React Native Modal is a separate window, so it swallows touches from everything below.</description>
      <category>react native modal</category>
      <category>onboarding</category>
      <category>react native</category>
      <category>react navigation</category>
      <category>mobile app bugs</category>
      <category>touch handling</category>
    </item>
    <item>
      <title>Scheduled notifications outlive the account that created them</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-11-scheduled-notifications-account-switch/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-11-scheduled-notifications-account-switch/</guid>
      <pubDate>Tue, 11 Aug 2026 00:00:00 GMT</pubDate>
      <description>After a sign-out, the previous user&apos;s tasks kept firing on my lock screen. Scheduled notifications live in a per-device OS queue that auth state never touches.</description>
      <category>scheduled notifications</category>
      <category>expo-notifications</category>
      <category>react native</category>
      <category>android alarmmanager</category>
      <category>account switching</category>
      <category>mobile app bugs</category>
    </item>
    <item>
      <title>Turborepo said cache hit and restored nothing</title>
      <link>https://www.kiniinsight.com/en/posts/2026-08-11-turborepo-cache-hit-restored-nothing/</link>
      <guid isPermaLink="true">https://www.kiniinsight.com/en/posts/2026-08-11-turborepo-cache-hit-restored-nothing/</guid>
      <pubDate>Tue, 11 Aug 2026 00:00:00 GMT</pubDate>
      <description>Turborepo reported FULL TURBO in 62ms and wrote zero build artifacts. The cause was one line in outputs, sitting behind a root task that had not run for 71 days.</description>
      <category>turborepo</category>
      <category>monorepo</category>
      <category>build cache</category>
      <category>turbo.json</category>
      <category>pnpm workspace</category>
      <category>cache invalidation</category>
      <category>CI</category>
    </item>
  </channel>
</rss>