<?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>Vibe Coding on Chinese Man</title><link>https://chineseman.net/categories/vibe-coding/</link><description>Recent content in Vibe Coding 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>Sat, 20 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://chineseman.net/categories/vibe-coding/index.xml" rel="self" type="application/rss+xml"/><item><title>How to Prompt an AI Coding Assistant: Lessons from Shipping Real Apps</title><link>https://chineseman.net/how-to-prompt-ai-coding-assistant/</link><pubDate>Sat, 20 Jun 2026 00:00:00 +0000</pubDate><guid>https://chineseman.net/how-to-prompt-ai-coding-assistant/</guid><description>The difference between an AI assistant that ships features and one that wastes your time is mostly how you prompt it. Practical prompting habits, with examples, from building and shipping real apps solo.</description><content:encoded><![CDATA[<p>The same AI coding assistant can feel like a senior engineer or like a confused intern,
and most of the difference is <em>how you talk to it</em>. After shipping a stack of apps this
way, these are the prompting habits that consistently get good code instead of
plausible-looking garbage. None of them are clever tricks. They are just good delegation.</p>
<h2 id="describe-the-outcome-not-the-implementation">Describe the outcome, not the implementation</h2>
<p>Amateur prompt: &ldquo;add a useState and a button that calls saveDraft.&rdquo; Better prompt: &ldquo;users
should be able to save a draft and come back to it later.&rdquo; Tell it <strong>what should be true
for the user</strong>, and let it propose the implementation. You will often get a cleaner
approach than the one you would have dictated, because you stopped constraining it to your
first idea, and you stay focused on the product instead of the syntax.</p>
<p>The deeper reason this works: when you specify the implementation, you cap the quality at
your own first guess. When you specify the outcome, the model can bring patterns you did
not think of. You are hiring it for its breadth, so do not handcuff it to your narrowest
instruction.</p>
<h2 id="give-it-the-context-it-cannot-see">Give it the context it cannot see</h2>
<p>The model does not know your stack, your conventions, or last week&rsquo;s decisions unless you
tell it. Most &ldquo;the AI did it wrong&rdquo; moments are really &ldquo;I did not give it the context to
do it right.&rdquo; Up front, hand it:</p>
<ul>
<li>the language and framework, and the key libraries you are using,</li>
<li>the relevant files or patterns to follow, for example &ldquo;match how <code>auth.ts</code> does this,&rdquo;</li>
<li>any hard constraints, like &ldquo;no new dependencies&rdquo; or &ldquo;this must work offline.&rdquo;</li>
</ul>
<p>Context is the cheapest quality improvement available. Thirty seconds of setup prevents an
hour of fixing a technically-correct answer that ignored how your project actually works.</p>
<h2 id="work-in-small-reviewable-slices">Work in small, reviewable slices</h2>
<p>Ask for one thing at a time. A single function, screen, or behavior produces a diff you can
actually read and verify. Giant &ldquo;build the entire feature&rdquo; prompts produce output you will
either rubber-stamp, which is dangerous, or spend longer untangling than you would have
spent writing it yourself, which defeats the point. Small slices keep you in control and
keep the AI&rsquo;s mistakes small and obvious instead of large and buried.</p>
<h2 id="show-do-not-just-tell">Show, do not just tell</h2>
<p>If you have an existing pattern, point at it: &ldquo;do this the same way the settings screen
handles state.&rdquo; Concrete examples constrain the model far better than adjectives ever
will. &ldquo;Make it clean&rdquo; means nothing, because the model has no idea what clean means to you.
&ldquo;Follow the structure of this file&rdquo; means everything, because now it has a target. When in
doubt, give it an example to imitate rather than a quality to aspire to.</p>
<h2 id="state-the-constraints-and-the-do-nots">State the constraints and the &ldquo;do not&quot;s</h2>
<p>Models default to adding things, more libraries, more abstraction, more cleverness. If you
do not want that, say so explicitly: &ldquo;do not add a dependency,&rdquo; &ldquo;do not change the public
API,&rdquo; &ldquo;keep this component presentational.&rdquo; A few clear guardrails prevent most of the
scope creep that quietly bloats a project over time. The model is not going to guess your
boundaries, so draw them.</p>
<h2 id="ask-it-to-explain-not-just-produce">Ask it to explain, not just produce</h2>
<p>When a change is non-trivial, ask &ldquo;why this approach?&rdquo; or &ldquo;walk me through what this does.&rdquo;
You get two wins. First, you catch flawed reasoning before it ships, while it is still
cheap to fix. Second, you actually learn the code you are responsible for, instead of
accumulating mystery. And if the explanation comes back hand-wavy or contradictory, that
is a loud signal to slow down and look harder, because the model may be papering over
something it does not actually understand either.</p>
<h2 id="treat-the-first-output-as-a-draft">Treat the first output as a draft</h2>
<p>The first response is a starting point, not a verdict. &ldquo;Good, but handle the empty case.&rdquo;
&ldquo;Simplify this, it is overengineered.&rdquo; &ldquo;That works, now do the boring version.&rdquo; Iteration
is the normal, expected path, not a sign you prompted wrong. Some of the best results come
from three rounds of &ldquo;almost, but&rdquo; rather than one perfect prompt, so do not treat the
first answer as final just because it looks finished.</p>
<h2 id="keep-a-context-file-you-reuse">Keep a context file you reuse</h2>
<p>Maintain a short document, your stack, your conventions, the things to never do, and feed
it at the start of sessions. It stops you from re-explaining yourself every time and stops
the model from re-introducing the same mistakes you corrected yesterday. It is the
single highest-leverage prompt you will write, because unlike every other prompt, you write
it once and it improves every session that follows.</p>
<h2 id="when-the-ai-gets-stuck-change-the-question">When the AI gets stuck, change the question</h2>
<p>Sometimes the assistant loops, producing slight variations of the same broken thing. That
is your cue to stop repeating the prompt and change it. Give more context, break the task
smaller, paste the actual error, or describe the goal a different way. Hammering the same
prompt harder rarely works. Reframing it almost always does, because the model was
missing information, not effort.</p>
<h2 id="verify-before-you-trust">Verify before you trust</h2>
<p>One habit underpins all of the above: never let good prose lull you into skipping
verification. A confident, well-formatted answer is not evidence that the code is correct,
only evidence that the model writes fluently, which it always does. So after every
non-trivial change, run it, read it, and check the part that actually matters against
reality: the real API, the real data, the real edge case. The assistant&rsquo;s job is to produce a
strong draft, fast. Your job is to be the one who confirms it is actually true before it
ships. Keep that division of labor sharp and the speed of vibe coding never curdles into a
steady stream of confident, plausible bugs.</p>
<h2 id="the-mindset">The mindset</h2>
<p>Good prompting is just good delegation: a clear outcome, enough context, a tight scope, and
verification at the end. Treat the assistant like a fast junior developer you trust to
draft but not to decide, and you will get most of the speed of vibe coding with little of
the mess. The broader philosophy behind all of this is in
<a href="/what-vibe-coding-actually-is/">what vibe coding actually is</a>, and the specific
traps to avoid are in <a href="/vibe-coding-mistakes-to-avoid/">9 vibe coding mistakes</a>.</p>
]]></content:encoded></item><item><title>My Vibe Coding Toolkit: What I Use to Ship Solo</title><link>https://chineseman.net/my-vibe-coding-toolkit/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://chineseman.net/my-vibe-coding-toolkit/</guid><description>The actual stack I use to design, build, ship, and host apps by myself: AI coding tools, frameworks, hosting, and the glue that holds a one-person operation together, organized by the job each tool does.</description><content:encoded><![CDATA[<p>People ask what tools I use far more than they ask about strategy, so here is the
honest stack, the things I actually open every day to ship as a team of one. Tools
change constantly, but the <em>categories</em> do not, so I have organized this by the job
each one does rather than by brand. Steal the structure, swap the specifics for
whatever is best when you read this.</p>
<h2 id="ai-coding-the-engine">AI coding: the engine</h2>
<p>This is the heart of the whole operation. I lean on an <strong>AI coding assistant</strong> that can
read my entire project, not just a single file, so it understands context and can make
changes across the codebase, run commands, and check its own work. A tool that only
sees one file at a time is a glorified autocomplete. One that understands the whole
repo is a collaborator.</p>
<p>But the tool matters less than the skill of using it. Small slices, clear outcomes, and
reading every diff will beat a fancier tool used carelessly every single time. A great
assistant with lazy prompting still ships bugs, fast. If you take one thing from this
list, make it that. The details are in
<a href="/what-vibe-coding-actually-is/">what vibe coding actually is</a>.</p>
<h2 id="frameworks-i-reach-for">Frameworks I reach for</h2>
<p>The rule here is boring on purpose. Boring means well-documented, which means the AI has
seen a million examples and gets it right, and means Stack Overflow already has the fix
when something breaks.</p>
<ul>
<li><strong>Mobile:</strong> a cross-platform framework so one codebase ships to both iOS and Android.
As a solo developer, maintaining two separate native apps is a non-starter. One
codebase, two stores.</li>
<li><strong>Web tools:</strong> whatever is mature and conventional. I avoid the framework that came
out last month, no matter how exciting, because the AI does not know it well yet and
neither do I.</li>
<li><strong>Static sites (like this blog):</strong> <a href="https://gohugo.io">Hugo</a>. Markdown in, fast static
HTML out, free to host, and nothing to patch at two in the morning. Perfect for
content and for app splash pages.</li>
</ul>
<h2 id="hosting-and-infrastructure">Hosting and infrastructure</h2>
<p>The guiding principle: the best infrastructure for a solo developer is the
infrastructure you never have to think about.</p>
<ul>
<li><strong>Static hosting:</strong> a CDN-backed static host (Vercel, Cloudflare Pages, Netlify all
have generous free tiers). My blog and every app splash page live here for free.</li>
<li><strong>DNS and CDN:</strong> Cloudflare. Cheap, fast, and the dashboard does not fight me.</li>
<li><strong>Backend, only when needed:</strong> a managed backend-as-a-service so I am not running and
patching servers. Many of my apps need no backend at all, which is the cheapest and
most reliable backend there is.</li>
</ul>
<p>A lot of my apps run entirely on-device, which means there is no server to scale, no
database to secure, and no monthly bill that grows with users. That is not an accident.
It is a deliberate choice that keeps a one-person operation sane.</p>
<h2 id="the-splash-page-pattern">The splash-page pattern</h2>
<p>Every app gets a subdomain with a single static page that does two things:</p>
<ul>
<li>detects mobile and routes straight to the App Store or Google Play, and</li>
<li>shows a description, screenshots, and a help or FAQ section on desktop.</li>
</ul>
<p>One link works everywhere, it costs nothing to host, and it doubles as the app&rsquo;s SEO
landing page. I drop that one link in any post or thread and it just does the right
thing for whoever clicks it.</p>
<h2 id="the-glue-that-holds-it-together">The glue that holds it together</h2>
<p>This is the unglamorous layer that makes the rest survivable.</p>
<ul>
<li><strong>Git, committed constantly.</strong> This is my undo button for vibe coding. When a prompt
makes things worse, and it will, I roll back in seconds instead of losing an
afternoon. Frequent small commits are not optional in this style of building.</li>
<li><strong>A project context file.</strong> A short doc of stack, conventions, and &ldquo;do not do this&rdquo;
rules that I feed the assistant at the start of a session. It stops the AI from
reintroducing the same mistakes and re-explaining the project every time.</li>
<li><strong>A plain notes file for the backlog.</strong> Half of shipping is deciding what <em>not</em> to
build this week. A running list keeps the good ideas from derailing the current one.</li>
<li><strong>Analytics that respect privacy.</strong> Just enough to know which articles get read and
which apps get used, without turning my users into a product.</li>
</ul>
<h2 id="what-i-deliberately-do-not-use">What I deliberately do not use</h2>
<ul>
<li><strong>Heavy project management tools.</strong> For one person, a Kanban board with seven columns
is procrastination with a nice UI. A text file and a short memory work better.</li>
<li><strong>Bleeding-edge frameworks.</strong> I want the AI to know the answer and the internet to
have the fix. Popular and slightly boring beats new and shiny every time.</li>
<li><strong>Anything that needs a server I have to babysit,</strong> unless there is genuinely no way
around it. Every running service is a thing that can break while I sleep.</li>
</ul>
<h2 id="a-word-on-choosing-tools">A word on choosing tools</h2>
<p>Notice that almost none of this is about picking the single best tool. It is about picking
tools that get out of your way and that you can replace without drama. I deliberately avoid
anything that locks me in: a proprietary format I cannot export, a host I cannot leave, a
framework only one company truly understands. The reason is simple. As a solo builder, my
scarcest resource is attention, and every tool that demands ongoing care is a tax on it. So I
optimize for boring, swappable, and well-documented over clever and trendy, every time. The
best tool is usually the one you stop having to think about the day after you adopt it, and
the worst is the impressive one that quietly becomes a part-time job to maintain.</p>
<h2 id="the-takeaway">The takeaway</h2>
<p>The stack matters far less than the loop: describe, generate, <strong>read</strong>, run, commit,
repeat. Pick boring, well-documented tools so your assistant is fluent in them, host on
free static tiers until you have real traction, and keep your operation small enough
that one person can hold the whole thing in their head. That last constraint is the
real secret. Every tool I choose is chosen to protect it. When you can fit the entire
system in your mind, you move fast and you sleep at night, and as a solo builder those
two things are the whole game.</p>
]]></content:encoded></item><item><title>9 Vibe Coding Mistakes That Quietly Wreck Your Project</title><link>https://chineseman.net/vibe-coding-mistakes-to-avoid/</link><pubDate>Wed, 17 Jun 2026 00:00:00 +0000</pubDate><guid>https://chineseman.net/vibe-coding-mistakes-to-avoid/</guid><description>Vibe coding ships fast, and fails quietly when you skip the fundamentals. The nine mistakes that turn AI-assisted speed into a pile of bugs, why each one is so easy to make, and how to avoid them.</description><content:encoded><![CDATA[<p>Vibe coding lets a solo builder move at a pace that used to require a whole team. It also
lets you generate a disaster at that same pace if you are sloppy, and the disasters are
quiet, they do not announce themselves until much later. After shipping a bunch of apps
this way, here are the mistakes I see most often, including ones I have made myself, and
how to dodge each one.</p>
<h2 id="1-not-reading-the-diff">1. Not reading the diff</h2>
<p>This is the single most expensive habit, and it is the root of most of the others. If you
accept changes you have not read, you are not building software, you are accumulating
mystery. Each unread change is a thing you do not understand sitting in your codebase,
waiting. Read every change. If you do not understand it, ask the AI to explain it or
rewrite it until you do. The moment you start rubber-stamping diffs to go faster is the
moment you start going slower, you just will not find out for a week.</p>
<h2 id="2-asking-for-too-much-at-once">2. Asking for too much at once</h2>
<p>&ldquo;Build the whole app&rdquo; produces a thousand lines you cannot review and cannot debug. The
output looks impressive and is nearly useless, because you have no idea which parts are
right. Work in <strong>small slices</strong>, one feature, one function, one screen at a time. Small
diffs are reviewable. Mega-dumps are just hope wearing a confident face. Slicing the work
small is not slower overall, it is what keeps you from drowning later.</p>
<h2 id="3-no-version-control-or-rare-commits">3. No version control, or rare commits</h2>
<p>Vibe coding is intensely iterative, and iteration goes sideways constantly. Git is your
undo button. Commit every single time something works, so that when the next prompt makes
things worse, and it regularly will, you roll back in seconds instead of trying to
manually un-break a tangle. Builders who commit rarely lose whole afternoons to a change
they cannot cleanly reverse. Cheap, frequent commits are not bureaucracy here, they are
the safety net that makes fast iteration survivable.</p>
<h2 id="4-trusting-confident-wrong-answers">4. Trusting confident wrong answers</h2>
<p>AI will invent an API that does not exist and present it like established fact. It will be
just as fluent and self-assured when it is wrong as when it is right, which is what makes
it dangerous. Confidence is not correctness. Anything load-bearing, a library call, a
config value, a security assumption, gets verified against the real documentation, not
trusted because it sounded authoritative.</p>
<h2 id="5-skipping-the-run-it-loop">5. Skipping the run-it loop</h2>
<p>Generating code without running it constantly is just producing plausible-looking text.
It compiles in your imagination and breaks in reality. Run the app after every meaningful
change. The feedback loop <em>is</em> the work. Skip it and you will eventually run everything at
once and discover ten broken things tangled together, with no idea which change caused
which failure.</p>
<h2 id="6-letting-the-architecture-drift">6. Letting the architecture drift</h2>
<p>Every prompt nudges the structure a little. Twenty unsupervised nudges later your codebase
is mush, with duplicated logic, three different ways to do one thing, and no clear
boundaries. The AI optimizes for making <em>this</em> change work, not for the long-term shape of
your system, so that responsibility is yours. Periodically step back and steer:
&ldquo;consolidate this,&rdquo; &ldquo;extract that,&rdquo; &ldquo;keep this layer thin.&rdquo; Architecture is the one thing
you cannot delegate.</p>
<h2 id="7-no-project-context-file">7. No project context file</h2>
<p>Without a short document of your stack, your conventions, and your &ldquo;do not do X&rdquo; rules,
the AI cheerfully reintroduces the same mistakes and ignores the patterns you have already
established, because it has no memory of yesterday. A small context file you feed it at the
start of each session saves you from correcting the identical thing forever. It is the
highest-leverage thing you can write, because you write it once and it pays off in every
session after.</p>
<h2 id="8-vibe-coding-the-critical-20-percent">8. Vibe coding the critical 20 percent</h2>
<p>Auth, payments, data integrity, anything security-sensitive, these are exactly where a
subtle generated bug is catastrophic rather than annoying. This is the part of the app
where &ldquo;looks right&rdquo; is nowhere near good enough. Slow down here. Read every line twice,
test the edge cases deliberately, and do not hand the keys to an autocomplete. The speed
you gain everywhere else is what buys you the time to be careful here.</p>
<h2 id="9-outsourcing-your-understanding">9. Outsourcing your understanding</h2>
<p>The deepest trap of all: shipping code you fundamentally cannot explain. It works in the
demo, so you move on, and then the day it breaks in production, &ldquo;the AI wrote it&rdquo; does not
help you fix it and it does not help your users whose data is stuck. You are still the
engineer of record for every line, and understanding your own system is not optional. If
you could not, in a pinch, explain what a piece of code does and why, you do not actually
own it yet.</p>
<h2 id="the-meta-mistake-assuming-the-rules-do-not-apply-to-you">The meta-mistake: assuming the rules do not apply to you</h2>
<p>Underneath all nine is one final trap: believing that because the AI is so capable, you get to
skip the discipline the rest of us need. You do not. The more powerful the assistant, the more
damage a single unreviewed, untested, unloved change can do, precisely because it can touch
more of your codebase faster. Capability raises the stakes of carelessness, it does not lower
them. The builders who get burned worst are usually the ones who were most impressed by the
tool and therefore trusted it the most, skipping the diff and the test run because surely
something this smart would not be wrong. Stay a little skeptical, keep the habits, and you
stay safe no matter how good the model gets.</p>
<h2 id="the-thread-connecting-all-nine">The thread connecting all nine</h2>
<p>Every one of these mistakes is really the same lesson wearing a different outfit: <strong>vibe
coding moves the work up a level, it does not remove it.</strong> You stop typing boilerplate and
start spending your attention on review, direction, and judgment. That is a fantastic
trade, but it is still a trade, not a free lunch. Builders who treat the AI as a fast
junior developer they actively supervise ship genuinely great things, quickly. Builders
who treat it as an infallible oracle ship bugs at record speed and call it productivity.</p>
<p>The good news is that avoiding all nine is mostly a matter of discipline, not talent. Read
the diff, slice the work, commit often, verify the risky parts, and keep understanding
what you ship. For the positive version of this, the workflow and tools that make it go
right, see <a href="/what-vibe-coding-actually-is/">what vibe coding actually is</a> and
<a href="/how-to-prompt-ai-coding-assistant/">how to prompt an AI coding assistant</a>.</p>
]]></content:encoded></item><item><title>What Vibe Coding Actually Is (And How I Ship With It)</title><link>https://chineseman.net/what-vibe-coding-actually-is/</link><pubDate>Sat, 13 Jun 2026 00:00:00 +0000</pubDate><guid>https://chineseman.net/what-vibe-coding-actually-is/</guid><description>Vibe coding is not &amp;#34;the AI does everything.&amp;#34; Here is what it really means, where it shines, where it bites, the exact loop I use to ship apps with it, and how it changes the job of building software.</description><content:encoded><![CDATA[<p>&ldquo;Vibe coding&rdquo; gets thrown around like it means typing a wish into a chatbot and
receiving a finished app. That is not what it is, and believing that is the fastest
way to ship something broken. Here is the honest version, based on how I actually
build and ship apps as a team of one.</p>
<h2 id="a-working-definition">A working definition</h2>
<p>Vibe coding is describing what you want in plain language and letting an AI write
most of the code, while you stay the architect, reviewer, and tester. You are still
in charge. You are just not typing every line.</p>
<p>The real shift is from <em>author</em> to <em>editor</em>. For most of software history, your value
was in producing code: remembering syntax, wiring up boilerplate, looking up the API
for the hundredth time. Vibe coding takes that production cost close to zero and moves
your value to judgment: deciding what should exist, recognizing whether the output is
correct, and steering when it drifts. You spend less time typing and more time
thinking about the product.</p>
<p>That sounds small. It is not. It is the difference between writing a paragraph and
editing one. An editor with taste and a fast writer can produce a book quickly. An
editor with no taste and a fast writer produces a fast pile of nonsense. The writer
got faster either way. Whether that is good depends entirely on the editor.</p>
<h2 id="a-concrete-example-of-the-loop">A concrete example of the loop</h2>
<p>Say I want a &ldquo;save draft&rdquo; feature. The old way: I open the file, remember the state
management pattern, write the handler, wire the button, add storage, debug the typos.
Twenty minutes if I am lucky.</p>
<p>The vibe-coding way: I tell the assistant, &ldquo;Let users save a draft and reopen it
later. Match how the settings screen persists data.&rdquo; It produces the handler, the
storage call, and the button in seconds. Then my real work starts. I read the diff.
Does it handle the empty draft? Does it collide with an existing key? Is the storage
call the one we already use elsewhere, or did it invent a second pattern? I fix what
is off, run the app, confirm it works, and commit. Total time: maybe five minutes,
and the thinking happened where it mattered.</p>
<h2 id="where-it-genuinely-shines">Where it genuinely shines</h2>
<ul>
<li><strong>First drafts of anything.</strong> A new screen, an API endpoint, a config file. The AI
gets you to 80 percent in seconds, and 80 percent of something is far easier to
finish than a blank file.</li>
<li><strong>Unfamiliar territory.</strong> New framework, new language, a library you have never
touched. The model already knows the idioms you would otherwise spend an hour
googling, so the learning curve flattens.</li>
<li><strong>Boilerplate and glue.</strong> CRUD, forms, parsers, scripts, tests, type definitions.
The boring 60 percent of every project that you have written a hundred times before.</li>
<li><strong>Refactors you have been avoiding.</strong> &ldquo;Extract this into a service, add error
handling, keep the behavior identical.&rdquo; Tedious by hand, quick to supervise.</li>
</ul>
<p>This is the reason a solo builder can now ship what used to take a small team. The
production bottleneck is gone, so you are limited by how fast you can decide and
verify, not how fast you can type.</p>
<h2 id="where-it-bites">Where it bites</h2>
<ul>
<li><strong>Confident wrong answers.</strong> The AI will invent an API that does not exist and write
it like gospel. If you cannot tell, you will ship it. Confidence is not correctness.</li>
<li><strong>Silent drift.</strong> Each prompt nudges the code. Twenty prompts later the architecture
is mush, with duplicated logic and three ways to do one thing, if you were not
watching.</li>
<li><strong>The 20 percent that matters most.</strong> Auth, payments, data integrity, security. The
parts where a subtle bug is expensive are exactly where you must slow down and read
every line.</li>
</ul>
<p>I learned the drift one the hard way. Early on I let an assistant add feature after
feature to an app without stepping back, and a week later I had three different ways
of storing the same data and a bug that touched all three. The fix took longer than
building it properly the first time would have. Now I steer the structure
deliberately instead of letting it accrete.</p>
<p>The rule I live by: you are responsible for every line you ship, whether you typed it
or not. &ldquo;The AI wrote it&rdquo; is not a defense to your users when their data is gone.</p>
<h2 id="the-loop-i-actually-use">The loop I actually use</h2>
<ol>
<li><strong>Describe the outcome, not the implementation.</strong> &ldquo;Users can save a draft and come
back to it&rdquo; beats &ldquo;add a useState and a button.&rdquo; Let the model propose the how.</li>
<li><strong>Work in small slices.</strong> One feature, one screen, one function at a time. Small
diffs are reviewable. Thousand-line dumps are not.</li>
<li><strong>Read the diff every time.</strong> Non-negotiable. If I do not understand a change, I ask
the AI to explain it or I rewrite it until I do.</li>
<li><strong>Run it immediately.</strong> Vibe coding without running the app constantly is just
generating hope. The feedback loop is the work.</li>
<li><strong>Commit when it works.</strong> Frequent commits give me a safe point to roll back to
when the next prompt makes things worse, which it regularly does.</li>
<li><strong>Keep a project context file.</strong> A short doc of stack, conventions, and &ldquo;do not do
X&rdquo; that I feed the assistant so it stops reintroducing the same mistakes.</li>
</ol>
<h2 id="what-actually-changes-about-the-job">What actually changes about the job</h2>
<p>The fear is that vibe coding makes engineering skill worthless. The opposite is true.
When anyone can generate code, the scarce skills become the ones the AI does not have:
knowing what to build, recognizing a bad solution, understanding the system well
enough to catch the subtle break, and having the taste to keep things simple. Those
are senior skills, and vibe coding rewards them more, not less. The junior who only
ever copied the generated answer never develops them. The builder who reads, questions,
and steers gets sharper with every project.</p>
<h2 id="the-mindset-that-makes-it-work">The mindset that makes it work</h2>
<p>Treat the AI like a fast, eager junior developer with no memory and no judgment about
<em>your</em> product. It produces a lot, quickly, and it will confidently do the wrong thing
if you let it. Your job did not disappear. It moved up a level, to direction, taste,
and verification.</p>
<p>That is the trade. You give up typing, you keep the thinking. Done right, you ship in
a weekend what used to take a month. Done lazily, you ship bugs at the same impressive
speed. The entire difference is how carefully you stay in the loop. For the specific
habits that keep it on the rails, see
<a href="/how-to-prompt-ai-coding-assistant/">how to prompt an AI coding assistant</a> and
<a href="/vibe-coding-mistakes-to-avoid/">9 vibe coding mistakes to avoid</a>.</p>
]]></content:encoded></item><item><title>On-Device vs Cloud AI: How to Choose for Your App</title><link>https://chineseman.net/on-device-vs-cloud-ai/</link><pubDate>Sun, 07 Jun 2026 00:00:00 +0000</pubDate><guid>https://chineseman.net/on-device-vs-cloud-ai/</guid><description>Should your app run AI on the phone or call a cloud API? A practical comparison of on-device and cloud AI across privacy, cost, latency, capability, and offline use, with a clear way to decide which fits your app.</description><content:encoded><![CDATA[<p>When you add AI to an app, one architectural choice shapes almost everything that follows: does
the model run <strong>on the device</strong> or in <strong>the cloud</strong>? It affects your costs, your privacy story,
your speed, your offline behavior, and what the app can actually do. Most developers reach for
the cloud API by reflex because it is easiest to start with, but the right answer depends on
your app. Here is how the two compare and how to decide.</p>
<h2 id="the-quick-version">The quick version</h2>
<ul>
<li><strong>Cloud AI</strong> means your app sends data to a server running a large model, which sends back a
result. It is easy to build and gives you access to the most powerful models, but every call
costs money, needs a connection, and sends user data off the device.</li>
<li><strong>On-device AI</strong> means a smaller model runs directly on the phone. It is harder to build and
limited to smaller models, but it is private, free to run, and works offline.</li>
</ul>
<p>Now the details, because each axis matters differently for different apps.</p>
<h2 id="privacy">Privacy</h2>
<p>This is the starkest difference. With cloud AI, user data leaves the device and passes through
someone&rsquo;s servers, where it may be logged, retained, or used for training. For a casual app
that may be fine. For anything sensitive, voice notes, health data, private documents, it is a
real liability and a hard sell to privacy-conscious users.</p>
<p>With on-device AI, the data never leaves the phone. You can make a credible promise that you do
not see, store, or transmit it, because architecturally you cannot. That promise is not just
ethics, it is a marketing advantage, and it is the entire premise behind apps like my
<a href="/building-private-speech-to-text-whisper-app/">offline transcription app</a> and
<a href="/building-offline-ai-chat-app-personal-llm/">on-device chat app</a>. When privacy is the
selling point, on-device is not a preference, it is the requirement.</p>
<h2 id="cost">Cost</h2>
<p>Cloud AI charges you per request, forever. Every user, every interaction, adds to a bill that
grows with your success. That can be sustainable with the right pricing, but it also means a
free app with a viral spike can hand you a frightening invoice. You are renting intelligence
by the token.</p>
<p>On-device AI costs you nothing to run after the user downloads the model. A million users cost
the same as one: zero marginal inference cost. For a solo builder who wants to give an app away
or charge once without an ongoing bill, that economics is liberating, and it is closely tied to
how you can <a href="/how-to-price-your-app/">price the app</a>.</p>
<h2 id="latency-and-reliability">Latency and reliability</h2>
<p>Cloud calls depend on the network. They add round-trip latency and they fail when the
connection is bad, which for a mobile app is often: subways, planes, elevators, rural areas,
spotty wifi. Your app is only as reliable as the user&rsquo;s signal and your server&rsquo;s uptime.</p>
<p>On-device runs locally, so there is no network round trip and no dependency on a server staying
up. Response time depends on the phone, but it is consistent and it works in airplane mode. For
anything users expect to &ldquo;just work&rdquo; anywhere, offline capability is a genuine feature, not a
nice-to-have.</p>
<h2 id="capability">Capability</h2>
<p>Here the cloud wins, clearly. Cloud servers run the largest, most capable models, the ones that
write essays, reason through hard problems, and handle enormous context. On-device models are
necessarily smaller to fit in a phone&rsquo;s memory, so they are less capable on the hardest tasks.
A small on-device model is great for focused jobs, transcription, classification, summarizing,
quick chat, and weaker at open-ended reasoning that demands a frontier model.</p>
<p>So the honest question is not &ldquo;which is smarter,&rdquo; it is &ldquo;how much capability does <em>my</em> feature
actually need?&rdquo; Many real app features need far less than people assume, and a small local model
handles them perfectly.</p>
<h2 id="how-to-decide">How to decide</h2>
<p>Run your app through these questions:</p>
<ul>
<li><strong>Is the data sensitive?</strong> If yes, lean on-device. Privacy is hard to retrofit.</li>
<li><strong>Do users need it to work offline?</strong> If yes, on-device, because the cloud simply cannot.</li>
<li><strong>Will inference costs threaten your economics at scale?</strong> If yes, on-device removes the bill.</li>
<li><strong>Does the feature genuinely require a frontier-level model?</strong> If yes, you may need the cloud,
at least for that piece.</li>
<li><strong>Are you optimizing for fastest time to ship a prototype?</strong> Cloud is easier to start with,
so it is a reasonable first move you can replace later.</li>
</ul>
<p>A useful pattern: prototype with the cloud to validate the feature quickly, then move the parts
that handle sensitive data or need to work offline onto the device once you know they are worth
keeping. You do not have to choose globally. You choose per feature.</p>
<h2 id="the-hybrid-path-is-often-the-real-answer">The hybrid path is often the real answer</h2>
<p>In practice, the choice is rarely all or nothing. Many of the best apps mix the two deliberately:
the sensitive, frequent, or offline-critical work runs on the device, while the occasional task
that genuinely needs a frontier model reaches out to the cloud, with the user&rsquo;s clear awareness. A
note-taking app might transcribe entirely on-device for privacy, but offer an optional cloud
summary that the user explicitly triggers. The trick is to make the boundary intentional and
transparent, so the user always knows when their data stays local and when it leaves. Done well, a
hybrid gives you most of the privacy and cost benefits of on-device with an escape hatch to cloud
power for the rare cases that truly need it. Just be honest about where that boundary sits, and
default to the device whenever you reasonably can.</p>
<h2 id="the-takeaway">The takeaway</h2>
<p>Cloud AI is the easy default and the right call when you need maximum capability and your data
is not sensitive. On-device AI is more work, but it wins decisively on privacy, cost, offline
reliability, and the ability to make promises you can actually keep. For a solo builder, that
combination, no server bill, no privacy liability, works anywhere, is often worth the extra
engineering, which is why so much of what I build runs on the phone rather than in someone
else&rsquo;s data center. Match the architecture to what your feature truly needs, and do not pay the
cloud&rsquo;s costs for capability you were never going to use.</p>
]]></content:encoded></item></channel></rss>