<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Apps on Chinese Man</title><link>https://chineseman.net/categories/apps/</link><description>Recent content in Apps on Chinese Man</description><image><title>Chinese Man</title><url>https://chineseman.net/logo.jpg</url><link>https://chineseman.net/logo.jpg</link></image><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 21 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://chineseman.net/categories/apps/index.xml" rel="self" type="application/rss+xml"/><item><title>How I Built a Private, On-Device Speech-to-Text App with Whisper</title><link>https://chineseman.net/building-private-speech-to-text-whisper-app/</link><pubDate>Sun, 21 Jun 2026 00:00:00 +0000</pubDate><guid>https://chineseman.net/building-private-speech-to-text-whisper-app/</guid><description>The story of building Private Transcribe, an offline speech-to-text app powered by Whisper that runs entirely on your phone in 99+ languages, so your audio never touches a server. Model tiers, the privacy angle, the UX around the model, and what I learned shipping it solo.</description><content:encoded><![CDATA[<p>Most transcription apps upload your audio to a server to process it. If you are recording
anything sensitive, a doctor&rsquo;s visit, an interview, a private voice note, a business call, that
is a hard no for me. So I built <strong>Private Transcribe</strong>: speech-to-text powered by <strong>Whisper</strong>,
running entirely on your device. The audio never leaves your phone. Here is how it came together,
and why one promise shaped every technical decision along the way.</p>
<div class="app-shots">
  <img src="/img/stt/1.png" alt="Private Transcribe recording screen with a tap-to-record button and an on-device transcription result offering play, copy, and share" loading="lazy">
  <img src="/img/stt/2.png" alt="Private Transcribe welcome screen prompting the user to download a Whisper speech-to-text model, marked On-Device" loading="lazy">
  <img src="/img/stt/3.png" alt="Private Transcribe model picker listing Whisper Tiny English and multilingual models with their download sizes" loading="lazy">
</div>
<h2 id="the-problem-with-free-transcription">The problem with &ldquo;free&rdquo; transcription</h2>
<p>Online transcription is rarely free in the way that counts. You pay with your audio. It gets
uploaded, processed on someone&rsquo;s servers, and often retained, sometimes to train the next version
of their model. For a casual voice memo, fine, maybe you do not care. For anything confidential,
you should, because the moment audio leaves your device you have lost control of it for good.</p>
<p>The promise I wanted to make and keep was plain: your audio never leaves your phone, and the app
never uploads your recordings or transcriptions anywhere. You can only say that with a straight
face if the app has no server in the loop at all. So it does not. Here, the missing backend is not
a limitation you apologize for. It is the whole point of the app.</p>
<h2 id="whisper-on-a-phone">Whisper on a phone</h2>
<p>The thing that makes this possible is <strong>Whisper</strong>, the open speech model that is startlingly good
across languages. Private Transcribe covers <strong>99+ languages</strong> through multilingual models, which is
a feature you could never offer cheaply if every minute of audio had to round-trip through your own
servers. On the device, languages are free.</p>
<p>The engineering problem, as with any on-device AI, is fitting a capable model onto a phone without
setting it on fire. Whisper ships in sizes, and the size you pick is a straight trade between speed,
accuracy, and storage. Rather than choose for the user, I put that decision in their hands as a
<strong>quality tier</strong>:</p>
<ul>
<li><strong>Tiny (75 MB):</strong> fastest, fine for quick notes where rough accuracy is enough.</li>
<li><strong>Base (142 MB):</strong> a balanced default that suits most people.</li>
<li><strong>Small (466 MB):</strong> clearly better for recordings that matter.</li>
<li><strong>Medium (1.5 GB):</strong> professional-grade accuracy for when it really counts.</li>
</ul>
<p>Someone on an older phone who wants speed grabs Tiny. Someone transcribing a crucial interview on a
newer device picks Medium and waits a bit longer for a cleaner result. Handing users the dial, with
a sensible default already chosen, beats pretending one size fits everyone. People know their own
situation better than I ever could from the other side of a screen.</p>
<h2 id="the-app-is-the-part-around-the-model">The app is the part around the model</h2>
<p>The model is the engine. The app is everything wrapped around it, and that wrapper is where most of
the product work lives:</p>
<ul>
<li><strong>Tap to record</strong> with real-time progress, so transcription feels alive instead of like staring
into a black box hoping something is happening.</li>
<li><strong>Local storage</strong> of every transcription, with <strong>search</strong>, so you can find that note from three
weeks ago without scrolling to the end of time.</li>
<li><strong>Sharing</strong> for the moments you <em>do</em> want a transcript to leave, on your terms, by a deliberate
tap, never on its own.</li>
<li>A calm <strong>dark interface</strong> that is easy on the eyes over long blocks of text.</li>
</ul>
<p>A surprising share of &ldquo;AI app&rdquo; work is precisely this unglamorous plumbing: making the model&rsquo;s
output findable, usable, and trustworthy. The intelligence is table stakes now. The product is the
wrapper, and a brilliant model behind a miserable interface is a brilliant model nobody opens twice.</p>
<h2 id="the-unglamorous-edges">The unglamorous edges</h2>
<p>Real recordings are a mess. People pause, ramble, and record for forty minutes straight. A toy demo
transcribes ten clean seconds. A real app has to chew through long audio without running the phone
out of memory, show honest progress on a file that takes a while, and never lose a transcription
because the app slipped into the background. None of that is exciting to build, and all of it is the
gap between a demo and something people trust with their week.</p>
<h2 id="where-vibe-coding-fit">Where vibe coding fit</h2>
<p>The AI assistant was a real force multiplier on the surrounding app: the recording screen, the
progress UI, the local database with search, the download and storage management, the share flow.
That is well-trodden ground it could scaffold quickly, which freed me up for the parts that mattered.</p>
<p>What stayed on me was the careful work: running Whisper efficiently on the device, handling long
recordings without choking on memory, and, above all, making sure the privacy promise held end to
end, with no sneaky analytics call quietly shipping audio off the phone. When your entire pitch is
privacy, the privacy has to be real, and that is the kind of thing you verify by reading every line
yourself instead of trusting whatever the assistant generated.</p>
<h2 id="why-on-device-was-worth-the-extra-pain">Why on-device was worth the extra pain</h2>
<p>Building this on the device was harder than gluing together a cloud API would have been. There was
no shortcut, no someone-else&rsquo;s-server to quietly hand the difficult part to. That difficulty is the
moat. Anyone can wrap a transcription API in a weekend, and a thousand people already have, which is
why those apps all blur into one. Almost nobody ships something that truly keeps your audio on your
phone, because it is more work and there is no per-minute usage to bill at the end. The hard path
turned out to be the defensible one, and the privacy that came with it is the reason someone picks
this app over the dozen cloud clones ranked above it in search.</p>
<h2 id="lessons">Lessons</h2>
<ul>
<li><strong>Privacy is a feature you can build a whole product around,</strong> but only if you mean it in the
architecture. &ldquo;On-device&rdquo; is a promise you earn in the code, not a badge you paste on the listing.</li>
<li><strong>Expose the real trade-off.</strong> Speed versus accuracy is personal, so let users pick their tier
instead of deciding for them.</li>
<li><strong>The wrapper is the product.</strong> Search, storage, sharing, and a quiet interface are what turn a
model into something people reach for daily.</li>
</ul>
<p>Private Transcribe follows a pattern in the things I build: take an AI capability everyone assumes
needs the cloud, and show it can run privately in your pocket. I did the same for chat in
<a href="/building-offline-ai-chat-app-personal-llm/">how I built an offline AI chat app</a>, and for something
lighter I went the other way entirely with a
<a href="/building-capybara-crossing-arcade-game/">capybara arcade game</a>.</p>
]]></content:encoded></item><item><title>Building Capybara Crossing: What Shipping a Casual Arcade Game Taught Me</title><link>https://chineseman.net/building-capybara-crossing-arcade-game/</link><pubDate>Thu, 18 Jun 2026 00:00:00 +0000</pubDate><guid>https://chineseman.net/building-capybara-crossing-arcade-game/</guid><description>The making of Capybara Crossing, an endless hop-across-the-road arcade game starring a capybara. Game feel, the anti-idle eagle mechanic, the coin economy, character unlocks, and the lessons from shipping a casual mobile game solo.</description><content:encoded><![CDATA[<p>After a long run of utility apps, I wanted to make something that was just fun. Something my
niece could pick up in two seconds with no tutorial and no explanation. The &ldquo;hop across endless
lanes of traffic&rdquo; formula is a classic for a reason, so I dropped a <strong>capybara</strong> into it and
built <strong>Capybara Crossing</strong>: hop across roads, train tracks, and rivers, grab coins, try not to
die. It turned out that a casual game is a completely different discipline from a tool, and it
taught me things the tools never did.</p>
<div class="app-shots">
  <img src="/img/capy/1.png" alt="Capybara Crossing title screen with the pixel-art capybara character, best score, and Play and Characters buttons" loading="lazy">
  <img src="/img/capy/2.png" alt="Capybara Crossing gameplay: the capybara dodging cars, buses, and trucks across a multi-lane road" loading="lazy">
  <img src="/img/capy/3.png" alt="Capybara Crossing gameplay crossing rivers and train tracks on log platforms while collecting coins" loading="lazy">
</div>
<h2 id="why-a-casual-game">Why a casual game</h2>
<p>Utility apps solve a problem. Casual games create a feeling. Those are different design jobs,
and I wanted reps in the second one. The bar is sneaky, too. The gameplay is simple, and simple
has nowhere to hide. If the hop does not feel good, there is no feature list to distract from it
and no settings screen to get lost in. The core loop is all you have, naked and exposed.</p>
<p>The pitch fits in a breath, which is the point. You are a capybara, the world is a wall of cars,
trucks, buses, trains, and rivers, and you hop forward as far as you can. Cute character, instant
understanding, one thumb. A five-year-old and a fifty-year-old both get it in the first second.</p>
<h2 id="feel-is-everything">Feel is everything</h2>
<p>In a utility app, &ldquo;it works&rdquo; is the finish line. In a game, &ldquo;it works&rdquo; is the floor. Feel is the
ceiling, and I poured a wildly disproportionate amount of time into things no spec sheet would
ever list:</p>
<ul>
<li><strong>The hop.</strong> Its timing, the little arc, the snap onto the next tile, the tiny squash on
landing. That one animation decides most of whether the game feels good or cheap.</li>
<li><strong>Readability.</strong> You have to see instantly where it is safe to land. Lane spacing, hazard
timing, and color all exist to make that obvious, because a death that feels unfair makes people
quit, and a death that feels earned makes them tap retry.</li>
<li><strong>The difficulty ramp.</strong> Gentle enough to start, mean enough that &ldquo;one more try&rdquo; gets its hooks
in you. The curve has to feel fair the whole way up.</li>
</ul>
<p>You cannot spec your way to good feel. You build it, play it a hundred times, nudge a single
number, and play it a hundred more. That loop is where most of the real work lives, and there is
no way around it. This is also where the AI hit its ceiling, which I will come back to.</p>
<h2 id="the-eagle-killing-the-just-stand-still-exploit">The eagle: killing the &ldquo;just stand still&rdquo; exploit</h2>
<p>Every endless hopper has the same flaw. Players figure out they can stop moving and sit there,
perfectly safe, forever. All the tension drains out. My fix is a threat wired straight into the
design: linger too long and an <strong>eagle drops out of the sky</strong> and carries you off. Keep moving or
else.</p>
<p>Tiny mechanic, huge effect. It deletes the safe option, holds the tension steady, and quietly
rewrites the game from &ldquo;dodge hazards when you feel like it&rdquo; into &ldquo;always be moving, manage the
danger as it comes.&rdquo; The best game design is often a single rule that pushes players toward the
behavior you want without a tutorial spelling it out. The eagle never explains itself. It teaches
you once, and you never stand still again.</p>
<h2 id="coins-characters-and-a-reason-to-come-back">Coins, characters, and a reason to come back</h2>
<p>A high score gets someone to play once. Progression gets them to come back. The loop is small:</p>
<ul>
<li>Grab <strong>coins</strong> while you hop, so every run has a second point beyond distance.</li>
<li>Spend them to <strong>unlock characters</strong>, six of them, including a Pirate, a Ninja, and a Space Capy.</li>
</ul>
<p>Cosmetic unlocks are a great fit for a casual game. They hand players goals without piling on
rules to memorize, and &ldquo;I just want the Space Capy&rdquo; turns out to be a surprisingly sticky reason
to keep playing. Everything is earnable by playing rather than paying, which keeps the game fair
and builds goodwill instead of resentment.</p>
<h2 id="where-vibe-coding-helped-and-where-it-quit-on-me">Where vibe coding helped, and where it quit on me</h2>
<p>AI assistance was great for the <strong>scaffolding</strong>: the core loop, procedural lane spawning,
collision detection, the coin and save system, the unlock screens. It got me from nothing to a
playable prototype fast, and fast is exactly what a fragile early game project needs, because the
window where you abandon it is right at the start. Reaching &ldquo;I can actually play this&rdquo; quickly is
what kept the whole thing alive.</p>
<p>What the AI could not do was tell me whether the game felt good. Tuning the hop, spacing hazards
so they are hard but fair, pacing the difficulty so it pulls you forward instead of pushing you
away, that is all taste and playtesting, and it stays human. An assistant hands you a working
game. Only playing it, over and over, turns a working game into a fun one. That split between
what the AI does and what you own is the same one I lean on everywhere.</p>
<h2 id="what-polish-actually-means">What polish actually means</h2>
<p>The biggest surprise was how much the invisible details mattered. A casual game lives or dies on
a hundred things no player could name: the exact beat before the eagle appears, the weight of a
landing, the half-second of feedback after a coin, the way the camera leans forward. None of it
shows up in a feature list, and all of it separates a game that feels cheap from one that feels
good in the hand. That attention to feel is a muscle. Build it on a game, where feel is the only
thing you have, and you start spotting the same missing polish everywhere else, in the tools you
were sure were already finished.</p>
<h2 id="what-shipping-it-taught-me">What shipping it taught me</h2>
<ul>
<li><strong>The first 30 seconds decide everything.</strong> Casual players judge fast. No fun first session,
no second session. The opening has to land.</li>
<li><strong>Juice matters.</strong> The sounds, the little animations, the satisfying coin pop. That feedback is
not decoration, it is the feel.</li>
<li><strong>Offline and free.</strong> No connection needed, progress saved locally, no paywall between the
player and the fun. Friction is the enemy of casual.</li>
<li><strong>Constraints breed charm.</strong> One capybara and one clean mechanic beat the sprawling design I
would never have finished. The limits made the game.</li>
</ul>
<p>Building a game after a stack of tools was the best thing I did for my craft all year. It drags
your attention onto feel, not just function, and that habit follows you home into everything else
you make, including the serious apps where &ldquo;it works&rdquo; was quietly never quite enough, like my
on-device <a href="/building-offline-ai-chat-app-personal-llm/">AI chat app</a> and
<a href="/building-private-speech-to-text-whisper-app/">private transcription app</a>.</p>
]]></content:encoded></item><item><title>How I Built an AI Chat App That Runs Entirely On Your Phone</title><link>https://chineseman.net/building-offline-ai-chat-app-personal-llm/</link><pubDate>Sun, 14 Jun 2026 00:00:00 +0000</pubDate><guid>https://chineseman.net/building-offline-ai-chat-app-personal-llm/</guid><description>The story of building Personal LLM, an offline, private AI chat app that runs Qwen 3 and GLM-Edge models on-device with no servers, no accounts, and no subscriptions. What was hard, what I learned about running language models on a phone, and how I shipped it solo.</description><content:encoded><![CDATA[<p>Every mainstream AI chat app ships your conversations off to someone&rsquo;s server. I wanted the
opposite: a model that runs on your phone, messages that never leave the device, no login,
no subscription. That app became <strong>Personal LLM</strong>, and getting a language model to behave
itself on a phone was the most interesting engineering problem I have taken on alone.</p>
<div class="app-shots">
  <img src="/img/llm/1.png" alt="Personal LLM model list showing Qwen 3 8B, Qwen 3 VL 8B vision, and Qwen 3 4B with sizes and RAM requirements" loading="lazy">
  <img src="/img/llm/2.png" alt="Personal LLM model list showing Qwen 3 1.7B, GLM-Edge 1.5B, and Qwen 3 0.6B on-device language models" loading="lazy">
  <img src="/img/llm/3.png" alt="Personal LLM chat screen running Qwen 3 0.6B entirely on-device, replying to a message while offline" loading="lazy">
</div>
<h2 id="the-itch">The itch</h2>
<p>Three things kept bugging me about the mainstream AI apps I was using.</p>
<ol>
<li><strong>Privacy.</strong> Everything you type goes to a server, and often into training data.</li>
<li><strong>Connectivity.</strong> On a plane or with one bar of signal, they are dead weight.</li>
<li><strong>Cost.</strong> Another $10 to $20 a month for something I use in unpredictable bursts.</li>
</ol>
<p>Meanwhile, on-device models had quietly gotten good. Good enough that I started to wonder what
it would take to make all three complaints disappear at once. An AI that just lived on your
phone, the way a calculator does, no strings attached. The idea nagged at me for weeks, so I
gave in and built it.</p>
<h2 id="the-hard-part-a-language-model-on-a-phone">The hard part: a language model on a phone</h2>
<p>This is the point where the project stops being a UI exercise and turns into a systems problem.
A phone is not a server, and its limits shape every decision you make.</p>
<ul>
<li><strong>Memory.</strong> A phone might have 4 to 8GB of RAM, and it is sharing that with the operating
system and every other app. A model that loads fine on a laptop gets killed on a phone
without ceremony. The OOM killer does not negotiate. That constraint alone rules out most
models before you start.</li>
<li><strong>Model size on disk.</strong> Nobody is going to sit through a 20GB download. Realistically you
have a few hundred MB to a few GB to work with.</li>
<li><strong>Speed.</strong> Tokens per second has to feel like a conversation. If it prints like a fax
machine, people close the app and never reopen it.</li>
<li><strong>Heat and battery.</strong> Push the processor flat out and the phone turns into a hand warmer and
the battery evaporates. The work has to be efficient, not merely possible.</li>
</ul>
<p>The thing that makes any of it work is <strong>small, quantized models</strong>. Quantization stores a
model&rsquo;s weights at lower precision, trading a little quality for a big drop in size and memory.
I built around <strong>Qwen 3</strong>, from tiny 0.6B variants up to larger ones, plus <strong>GLM-Edge</strong>,
including the vision-capable versions, with downloads landing somewhere between 500MB and 4GB.
You pick a model that fits your device, download it once, and after that it runs offline.</p>
<p>There is a trade-off you have to make peace with, and be upfront with users about. A 1B model
running on a phone is not a frontier model in the cloud. It will not write your dissertation.
For quick questions, drafting, summarizing, brainstorming, rewriting, and anything at 30,000
feet, it earns its keep, and it is <em>yours</em>. Saying that plainly inside the app beats
overpromising and losing someone on their first message.</p>
<h2 id="give-users-the-dials-but-hide-them-well">Give users the dials, but hide them well</h2>
<p>People want different behavior from a model, so I exposed the controls that matter: temperature,
top-k, and top-p for shaping how loose or focused the output is, plus a &ldquo;thinking&rdquo; mode against
a &ldquo;fast&rdquo; mode for when you want reasoning versus a quick reply. The danger with surfacing model
internals is drowning a casual user in knobs they did not ask for. So the rule was simple: every
control ships with a good default, and you can get a solid answer without ever opening the
settings. Tinkerers get their sliders. Everyone else gets something that works out of the box.</p>
<h2 id="where-vibe-coding-carried-me">Where vibe coding carried me</h2>
<p>I am one person. There was no way to ship this typing every line myself. The AI assistant took
the parts that are tedious but well understood:</p>
<ul>
<li>The <strong>chat UI</strong>: message bubbles, streaming tokens, scroll behavior, the copy button, the
empty state.</li>
<li>The <strong>model download manager</strong>: progress, resume after a dropped connection, storage checks,
deletion to reclaim space.</li>
<li>The <strong>settings layer</strong>: putting temperature, top-k, top-p, and the mode toggles somewhere a
normal person can safely ignore.</li>
</ul>
<p>What stayed on me was the hard 20 percent: wiring up on-device inference, managing memory so the
app does not get killed halfway through a reply, and tuning the defaults so a non-technical
person gets a good answer without touching a slider. The AI does the boilerplate, you own the
load-bearing parts. That division between what the AI drafts and what I own by hand is the thing
that makes the whole approach work.</p>
<h2 id="product-decisions-that-mattered">Product decisions that mattered</h2>
<ul>
<li><strong>One download, then offline forever.</strong> The only friction is that first model download. After
that, no network, no waiting.</li>
<li><strong>No account.</strong> An account is a privacy promise you can break. With none, there is nothing to
leak, nothing to breach, nothing to log into.</li>
<li><strong>Defaults first, depth optional.</strong> Casual users get a model that answers. Power users get the
sampling controls. Neither group pays for the other.</li>
<li><strong>Free.</strong> No servers means no costs to recover, which means no subscription, no billing, no
churn to manage.</li>
</ul>
<h2 id="what-i-would-tell-another-builder">What I would tell another builder</h2>
<p>On-device AI feels like magic to people because they assume it cannot be done. &ldquo;You can run
<em>that</em> on a phone?&rdquo; That gap between what people expect and what you shipped is a wonderful place
to stand, because the surprise does your marketing for you. Just respect the constraints. Match
models to device tiers, be honest about what a small model can and cannot do, and spend your
scarce hand-written hours on memory and performance, not on the parts an assistant can scaffold
before lunch.</p>
<p>What I ended up with is an app I reach for myself, on planes, on the subway, any time I would
rather not hand my private thoughts to a server. That is the bar I care about: would I use this
if I had not made it. Privacy-first building turned into a whole theme after this one, and I
followed the same thread into
<a href="/building-private-speech-to-text-whisper-app/">an offline speech-to-text app</a>.</p>
]]></content:encoded></item></channel></rss>