<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[coder000]]></title><description><![CDATA[coder000]]></description><link>https://coder000.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/6a9a1e06c4c50037751b6201/a29db4ce-162c-437a-9038-70620ffefa1d.png</url><title>coder000</title><link>https://coder000.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 14 Sep 2026 15:47:57 GMT</lastBuildDate><atom:link href="https://coder000.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[AI UI Design Without the Slop: Four Directions and a Choice]]></title><description><![CDATA[Season one of this story, From Prompt to Production, ended with a retrospective and a working app: ClinicLive books appointments, checks patients in at a kiosk, and calls them from a live waiting-room]]></description><link>https://coder000.hashnode.dev/ai-ui-design-without-the-slop-four-directions-and-a-choice</link><guid isPermaLink="true">https://coder000.hashnode.dev/ai-ui-design-without-the-slop-four-directions-and-a-choice</guid><category><![CDATA[AI]]></category><category><![CDATA[Design]]></category><category><![CDATA[UI]]></category><category><![CDATA[Blazor]]></category><dc:creator><![CDATA[Rahul Vyas]]></dc:creator><pubDate>Mon, 14 Sep 2026 14:07:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6a9a1e06c4c50037751b6201/708ef297-467f-42fb-a885-24db7c0c9843.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Season one of this story, <a href="https://www.coder000.com/post/ai-assisted-development-with-claude">From Prompt to Production</a>, ended with <a href="https://www.coder000.com/post/ai-development-cost-retrospective">a retrospective</a> and a working app: ClinicLive books appointments, checks patients in at a kiosk, and calls them from a live waiting-room board — tested, hardened, deployed. It also looks exactly like the template it was born from. This series is the design sequel: same repo, same AI pair, ten parts to close the gap between "works" and "looks like someone meant it."</p>
<h2>First, the before photos</h2>
<p>Before touching a line of CSS, we photographed everything. Partly for honesty — a redesign series that can't show its "before" is just a mood board — and partly because those photos turn out to be a working tool, not a keepsake. A quick Playwright script (it graduates into a proper harness in <a href="https://www.coder000.com/post/screenshot-loop-ai-design">Part 3</a>) captured all ten surfaces at their natural sizes: the booking page on a 375px phone, the kiosk on a tablet, the board and the staff pages at 1280.</p>
<p>Here is the waiting-room board — the screen that hangs on a wall and gets read from chairs:</p>
<p><img src="https://www.coder000.com/img/polish/before-board.png" alt="The waiting-room board in the old template: the left third is a purple gradient app sidebar with Home, Book, Cancel a booking, Check-in kiosk, Waiting room, Register and Login links; the board content — 'Waiting room', 'The next patient will be called shortly…' and an Up next list with two names — sits in small black text on white." />
<em>A waiting-room TV wearing an app sidebar — with Register and Login links. Fourteen parts of engineering, and the room sees a developer template.</em></p>
<p>And the booking page, the screen a stressed parent meets on a phone:</p>
<p><img src="https://www.coder000.com/img/polish/before-book-phone.png" alt="The booking page at 375px in the old template: a purple top bar with a hamburger menu, an About link, a 'Book an appointment' heading, a date field, and twenty-two identical small time buttons from 11:30 to 16:45 in a four-column grid." />
<em>Twenty-two identical buttons and no opinion about any of them. It works — season one proved that under test. It just doesn't care.</em></p>
<h2>Two bugs before a single design decision</h2>
<p>The before shoot was supposed to produce evidence. It produced findings. Look at that board screenshot again: the sidebar offers <strong>Register</strong> — and Register has been a 404 since <a href="https://www.coder000.com/post/ai-code-review-security-pass">Part 11's hostile review</a> deleted the whole self-registration surface. Nobody removed the sidebar link. Which means the TV on the waiting-room wall spent the rest of season one offering patients a link to an error page, and it survived a test suite, a hostile security pass, and a deploy checklist — because all of those read code, and in code nothing is wrong. A link to a deleted page is perfectly valid markup. It's only wrong on a television. One photo caught it.</p>
<p>The second finding came from the kiosk:</p>
<p><img src="https://www.coder000.com/img/polish/before-kiosk-error.png" alt="The check-in kiosk in the old template: purple gradient sidebar with Home, Book, Cancel a booking, Check-in kiosk, Waiting room, Register and Login links; a 'Welcome' heading with a waving-hand emoji, a wide dotted code input, a blue Check in button, and a green alert reading 'You're checked in! You are number 2 in the queue. Watch the board for your name.'" />
<em>The kiosk before-shot took two takes. The first run typed every seeded code and got "No appointment found" back — the demo appointments had quietly aged out, four days after <a href="https://www.coder000.com/post/deploying-blazor-signalr-vps">Part 12's</a> deploy. This green alert is the second take, after re-seeding.</em></p>
<p>The kiosk was being perfectly correct: those codes really did belong to appointments in the past, and refusing them is exactly what Part 11 would have demanded. But "correct" and "demo-able" are different claims, and demo data has a shelf life. Both bugs go in the log, both get fixed in the next two parts — and notice what found them: not a review prompt, not a test, a <em>camera</em>. Hold that thought until Part 3.</p>
<h2>Why AI design converges on slop</h2>
<p>Now the actual subject. Ask an AI to "make it look nice, modern and professional" and you will get the same app everyone else got: a purple gradient somewhere load-bearing, Inter on white, three feature cards with icons, generous rounded corners, a hero section congratulating you on visiting. This isn't a personality flaw — it's what a language model <em>is</em>. It predicts the likely continuation, and a generic prompt asks for the most likely design. A vague "make it nice" is, quite literally, a request for the average of the internet.</p>
<p>The trap has a second jaw. When the average design comes back, most of us can't articulate why it's wrong — "it looks AI-generated" isn't actionable feedback — so we ask for another pass, get a slightly different average, and settle. You can't art-direct what you can't name. The fix is to change the shape of the request so that naming happens up front.</p>
<h2>The technique: propose wide, choose narrow</h2>
<p>Instead of asking for a design, ask for <em>directions</em> — several of them, genuinely different, each pinned down hard enough to be judged. The ask is small; the constraints are the whole trick:</p>
<pre><code class="language-text">"Propose four visual directions for this app, and make them genuinely
different from each other. For each: a name, background / ink / accent
colors as hex, one typeface, and a single line on how it should feel.
No purple gradients, no default-font-on-white. Directions only — no
CSS yet."
</code></pre>
<p>Hex codes force commitment — "warm and inviting" is not falsifiable, <code>#FAF7F2</code> is. One line of feel keeps each direction honest about what it's for. And "no CSS yet" is the same clause that made season one's security review work: proposals first, so the human stays the judge. Here are the four that came back, exactly as proposed:</p>
<p><em>The four directions, as proposed</em></p>
<table>
<thead>
<tr>
<th></th>
<th>Direction</th>
<th>Palette &amp; type</th>
<th>Feels like</th>
</tr>
</thead>
<tbody><tr>
<td>A</td>
<td><strong>Calm Practice</strong></td>
<td>Warm paper <code>#FAF7F2</code>, ink <code>#1F2A2E</code>, sage <code>#5B8A72</code>, clay <code>#C4664B</code> for warnings · Atkinson Hyperlegible</td>
<td>A practice you trust</td>
</tr>
<tr>
<td>B</td>
<td><strong>Swiss Health</strong></td>
<td>Pure white, near-black, a single red <code>#D32F2F</code> accent, hard grid · Helvetica stack</td>
<td>Precision, zero warmth</td>
</tr>
<tr>
<td>C</td>
<td><strong>Night Shift</strong></td>
<td>Dark-first slate <code>#16181D</code>, cyan <code>#4DD0E1</code>, glowing board</td>
<td>Mission control</td>
</tr>
<tr>
<td>D</td>
<td><strong>Friendly Paper</strong></td>
<td>Cream, rounded everything, Fraunces serif accents</td>
<td>A children's clinic</td>
</tr>
</tbody></table>
<p>Four real options, and now choosing is a human-sized job. B is a beautiful poster and a cold clinic. C is right for exactly one of our surfaces — remember it when the board gets its own dark treatment in <a href="https://www.coder000.com/post/waiting-room-board-signage-ux">Part 6</a> — and wrong for a family clinic's public pages. D risks twee the moment it meets staff-page density. A is clinic-appropriate warmth, works in light and dark, and its typeface is a story in itself. We picked A.</p>
<blockquote>
<p>🧠 <strong>Model pick:</strong> Opus, high effort, for the directions. Divergence is a thinking task — asked for four directions, the cheap model tends to return one direction wearing four names. Everything else in this part (the before shoot, the revision below) is pennies on any model.</p>
</blockquote>
<h2>The human veto</h2>
<p>This is where the part earns its title. Tokens were about to be built on Calm Practice when a nagging feeling produced the most valuable prompt of the season so far, verbatim: <em>"it's not similar to my other project, right???"</em> — three question marks, because the feeling was already pretty sure. We opened the stylesheets of my other project, UnifiedSelf, and checked: cream <code>#F4F1E8</code>, green <code>#2C7A4B</code>, sage <code>#A8BDB6</code>, Fraunces. Direction A — warm paper, sage primary, serif-adjacent warmth — was its near-twin. The "distinctive" direction was distinctive against the internet and derivative against my own portfolio.</p>
<blockquote>
<p>🤖 <strong>What the AI got wrong:</strong> nothing it could have known — which is exactly the lesson. The model optimized "distinct from AI defaults" because that's what the prompt asked for and that's the corpus it can see. Your portfolio is the corpus it can't. "Distinctive" has two halves — distinct from the slop <em>and</em> distinct from your own prior work — and the second half is your job to bring: paste your other projects' palettes into the prompt, or expect a twin. The veto itself also doesn't delegate: the AI rated Calm Practice distinctive right up until it was shown otherwise.</p>
</blockquote>
<h2>v2: porcelain &amp; petrol</h2>
<p>The revision kept everything that was right about A — calm, light, accessible — and moved the hue away from my own shadow: cool instead of warm. <strong>"Calm Practice: porcelain &amp; petrol"</strong> — porcelain <code>#F5F8F8</code> background, white surfaces, ink <code>#182A2D</code>, petrol teal <code>#16696F</code> as the primary, coral <code>#C96F4A</code> as the accent, <code>#3E8460</code> for good news and <code>#B4473C</code> for bad. The dark set was priced on day one rather than bolted on later: <code>#101B1D</code> background, <code>#182527</code> surfaces, ink <code>#E4EDEC</code>, primary lifted to <code>#4FB3B8</code>.</p>
<p>The typeface survived both versions, and deserves its sentence: <strong>Atkinson Hyperlegible</strong> was designed by the Braille Institute for low-vision readers — its letterforms are deliberately unambiguous, so 1, l and I, or 0 and O, can't impersonate each other. A clinic's UI is read by anxious people, older people, and people squinting at a wall from five meters. That's an accessibility story built into a font choice, and <a href="https://www.coder000.com/post/ai-accessibility-audit-blazor">Part 8</a> will hold the rest of the design to the same standard.</p>
<h2>The plan for the season</h2>
<p>Two strategy decisions are already made, and both come from treating the redesign like the engineering project it is. First, foundations before beauty: Part 2 builds a token system and — the migration trick of the season — deletes Bootstrap while keeping its class <em>vocabulary</em>, so every page keeps compiling. The kiosk and the board become chrome-free "appliances," which is also the structural fix for that Register link. Second, after Part 3 makes the screenshot loop a real tool, each surface gets its own part as its own UX discipline: phone, touch, signage, pro tool. Four surfaces, four different sets of rules — that's the argument of the whole series.</p>
<blockquote>
<p>💸 <strong>The meter:</strong> season one closed at ≈ $6.20 total; season two's meter starts fresh. ≈ $0.40 so far — the before shoot, four directions, and the porcelain &amp; petrol revision. The most valuable contribution of the part — "it's not similar to my other project, right???" — was typed by a human, free of charge.</p>
</blockquote>
<blockquote>
<p>✅ <strong>Checkpoint:</strong> <code>git checkout part-12</code> in <a href="https://github.com/rahulvyas777/clinic-live">the repo</a> is forever the before photo: the board wears its sidebar, the sidebar offers Register, and Register 404s. The before screenshots are committed under <code>shots/before</code> — the next nine parts argue against that folder.</p>
</blockquote>
<p>Next, the foundation every later part will spend: every color a custom property, dark mode by redefining tokens instead of touching components, and Bootstrap deleted on the same day every page keeps compiling — <a href="https://www.coder000.com/post/design-tokens-with-ai-blazor">Part 2: Foundations: design tokens, dark mode — and killing Bootstrap</a>.</p>
<hr />
<p><em>Originally published at <a href="https://www.coder000.com/post/ai-ui-design-escaping-the-slop">coder000.com</a>. Part of the series <a href="https://www.coder000.com/series/from-prompt-to-polish">From Prompt to Polish</a> — read the whole series there.</em></p>
]]></content:encoded></item><item><title><![CDATA[The Retro: What ClinicLive Really Cost, and What the AI Got Wrong]]></title><description><![CDATA[Fourteen parts ago, this series made a promise: build a real app with AI and hide nothing — every prompt shown, every mistake kept, every dollar counted. ClinicLive is live behind nginx, its commit me]]></description><link>https://coder000.hashnode.dev/the-retro-what-cliniclive-really-cost-and-what-the-ai-got-wrong</link><guid isPermaLink="true">https://coder000.hashnode.dev/the-retro-what-cliniclive-really-cost-and-what-the-ai-got-wrong</guid><category><![CDATA[AI]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[Blazor]]></category><category><![CDATA[Career]]></category><dc:creator><![CDATA[Rahul Vyas]]></dc:creator><pubDate>Sat, 12 Sep 2026 01:41:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6a9a1e06c4c50037751b6201/f2f85bc5-52c7-4629-93e3-586bb73c9b16.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Fourteen parts ago, this series made a promise: build a real app with AI and hide nothing — every prompt shown, every mistake kept, every dollar counted. ClinicLive is live behind nginx, its commit messages are the prompt log, and the meter has stopped. Time to count.</p>
<h2>The bill, honestly</h2>
<p>These numbers come straight from the build log — cumulative API spend as each part of <a href="https://github.com/rahulvyas777/clinic-live">the app</a> landed:</p>
<p><em>What each part of ClinicLive cost in API spend</em></p>
<table>
<thead>
<tr>
<th>Part</th>
<th>What we built</th>
<th>Running total</th>
</tr>
</thead>
<tbody><tr>
<td><a href="https://www.coder000.com/post/writing-a-software-spec-with-ai">3</a></td>
<td>The spec (plus 9 clarifying questions)</td>
<td>≈ $0.40</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/designing-postgresql-schema-with-ai">4</a></td>
<td>PostgreSQL schema</td>
<td>≈ $0.60</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/scaffolding-blazor-server-with-ai">5</a></td>
<td>Blazor Server skeleton, entities, migration, seeder</td>
<td>≈ $1.10</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/building-crud-features-with-ai">6</a></td>
<td>The booking flow</td>
<td>≈ $1.80</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/signalr-live-updates-with-ai">7</a></td>
<td>Live queue: kiosk, board, SignalR hub</td>
<td>≈ $2.70</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/blazor-server-chat-presence-signalr">8</a></td>
<td>Staff chat, presence, typing</td>
<td>≈ $3.40</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/testing-ai-generated-code">9</a></td>
<td>Test suite vs a real PostgreSQL</td>
<td>≈ $4.10</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/debugging-with-ai">10</a></td>
<td>Two real bug hunts</td>
<td>≈ $4.90</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/ai-code-review-security-pass">11</a></td>
<td>The hardening pass</td>
<td>≈ $5.60</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/deploying-blazor-signalr-vps">12</a></td>
<td>Deploy runbook, nginx, systemd, CI</td>
<td>≈ $6.20</td>
</tr>
</tbody></table>
<blockquote>
<p>💸 <strong>The meter, final reading:</strong> ≈ $6.20 of API spend and roughly one hour of wall-clock AI-assisted building — for a Blazor Server app with PostgreSQL, two SignalR surfaces, auth, a nine-test suite against a real database, CI, and deploy artifacts. An honest estimate for hand-building the same thing: two to three <em>days</em>.</p>
</blockquote>
<p><em>How the meter is measured, throughout this series: it's the build's actual token consumption priced at the API list rates of the models used (the 🧠 boxes name them). If you work through a subscription plan instead of pay-per-token, your bill won't say "$6.20" — but the tokens burned are the same, so it's the honest apples-to-apples number.</em></p>
<p>Now the honesty that belongs next to that callout: <strong>the $6.20 is not the real cost.</strong> The real cost is the human time steering and reviewing — reading every diff, pasting the schema into a review before accepting it, saying no to SMS, noticing that "Test G" isn't "Test G." That time doesn't appear on any meter, and it is precisely the part you must not skip — because every mistake in the next table was caught by exactly that time, and the one that wasn't caught early (open self-registration) sat in the codebase for six parts. The dollars buy drafts. The review is where the app became correct.</p>
<h2>The complete mistake log</h2>
<p>Every 🤖 from fourteen parts, in one table:</p>
<p><em>What the AI got wrong, part by part</em></p>
<table>
<thead>
<tr>
<th>Part</th>
<th>What the AI got wrong</th>
</tr>
</thead>
<tbody><tr>
<td>3 — spec</td>
<td>Invented an SMS notification feature nobody asked for; wanted patient accounts until the non-goal was stated explicitly. Scope creep is a habit, not an accident.</td>
</tr>
<tr>
<td>4 — schema</td>
<td><code>timestamp</code> without a timezone; no index on the <code>appointment.patient_id</code> foreign key; a plain UNIQUE on the slot that would have blocked re-booking a cancelled appointment. The partial-index requirement had to come from us.</td>
</tr>
<tr>
<td>5 — skeleton</td>
<td>Left the SQLite package in the csproj "for tests"; didn't flag that the template's confirmed-account default would lock out every seeded staff login until we asked "why can't I log in?"</td>
</tr>
<tr>
<td>6 — booking</td>
<td>Treated clinic hours as UTC — wrong "today" for any clinic east of UTC, slot labels shifted by the offset. Compiled, demoed fine, quietly wrong about time. Fixed in Part 10.</td>
</tr>
<tr>
<td>7 — queue</td>
<td>CS0542: injected a <code>QueueService Queue</code> member into <code>Queue.razor</code> — a component can't have a member named after its own class.</td>
</tr>
<tr>
<td>8 — chat</td>
<td>Proposed an <code>[Authorize]</code> hub that a server-side component can never reach (the connection carries no browser cookie — 401 forever). And CS0542 <em>again</em>, Chat in <code>Chat.razor</code>.</td>
</tr>
<tr>
<td>9 — tests</td>
<td>Wrote the queue-order test by reading the code instead of the spec — a tautological test that passed against a bug. Also asserted "Test G" where the board masks to "Test G."</td>
</tr>
<tr>
<td>11 — hardening</td>
<td>The template's open self-registration had shipped unquestioned in Part 5: anyone on the network could create an account and walk into the staff area. Found only when we made the AI attack its own app.</td>
</tr>
</tbody></table>
<p>Sort that table by <em>kind</em> and a pattern jumps out. Syntax barely features — two CS0542s across fourteen parts, both fixed in seconds, is the entire compiler-error tally. Where the AI actually failed was <strong>your context</strong>: business rules (the queue order lived in the spec, not the code), time (whose "today"?), auth reality (which connection carries which cookie), scope (what "version 1" means). The training data taught it the world's code; nothing taught it your clinic. And notice the repeats — the same CS0542 twice, the same confident tone before and after every mistake. It doesn't learn your lessons between sessions. You have to carry them.</p>
<blockquote>
<p>🤖 <strong>What the AI got wrong:</strong> this whole post, condensed — almost never the syntax, reliably the context. Every mistake worth logging was about our rules, our timezone, our auth, our scope. That's not a flaw to wait out with better models; it's the permanent shape of the division of labor. The context is your job.</p>
</blockquote>
<h2>What the AI was brilliant at</h2>
<p>Fairness cuts both ways, and the wins were not small:</p>
<ul>
<li><strong>The scaffold.</strong> A complete Blazor Server solution with Identity, wired and running, in minutes. Nobody types that faster.</li>
<li><strong>The translation work.</strong> Spec to DDL, schema doc to EF Core entities, requirements to EditForms — mapping one precise representation onto another is its native gear.</li>
<li><strong>The test harness.</strong> The whole Testcontainers rig, and when told "no mocking library", a hand-written 30-line no-op <code>IHubContext</code> — a genuinely tasteful choice.</li>
<li><strong>The runbook.</strong> Part 12's DEPLOY.md, 2am checklist included, is better deployment documentation than most funded products ship.</li>
<li><strong>Explaining every error instantly.</strong> CS0542, "pending model changes", the 401 loop — each diagnosed and explained in seconds. As a tutor sitting inside your terminal, it has no precedent.</li>
</ul>
<blockquote>
<p>🧠 <strong>Model pick, the series rule:</strong> Opus-class where mistakes compound — the spec, the schema, the real-time design; Sonnet-class where the path is well-worn — the scaffold, CRUD, tests; cheap models for the mechanical. Fourteen parts never needed the rule revised: match spend to the consequence of error.</p>
</blockquote>
<h2>Saying "I built it with AI" in an interview</h2>
<p>Done wrong, it sounds like a confession. Done right, it's a hiring signal — and the difference is entirely in the story you can tell. Here's the ClinicLive version: the spec came first, and the AI interviewed <em>me</em> before writing it. Every prompt is recorded in a commit message, so the process is reviewable end to end. The tests were written from the spec, not from the code — and I can explain the tautological-test trap that rule prevents. A hostile review pass caught open self-registration before it shipped. I read every diff.</p>
<p>That story demonstrates spec thinking, review discipline, testing judgment and security awareness — the things interviews are trying to detect. The fear behind the question was always "can this person function without the tool?", and a story about <em>directing</em> the tool answers it better than pretending you don't use one. If interviews are on your horizon, the <a href="https://www.coder000.com/interview-prep">interview prep hub</a> is built for this, and <a href="https://www.coder000.com/post/ai-engineer-interview-prompt-context-questions">the AI interview series' prompting part</a> turns this series' habits into answers you can give under pressure.</p>
<h2>Keeping sharp</h2>
<p>The whole series' discipline, compressed to four lines worth pinning above your desk:</p>
<ul>
<li><strong>Read every diff.</strong> No exceptions, no "it's probably fine".</li>
<li><strong>Hand-write something weekly.</strong> The day you can't write it is the day you can't review it.</li>
<li><strong>Own the spec.</strong> Deciding what "correct" means is never delegated.</li>
<li><strong>Never ship what you can't explain.</strong> If you can't explain it, it isn't yours yet.</li>
</ul>
<blockquote>
<p>✅ <strong>Checkpoint, the last one:</strong> you've shipped a real app with AI — spec to schema to SignalR to a VPS, tested against a real database, hardened, deployed, and honestly accounted for. That's not a tutorial completed; that's a capability. Here's what to build next: something of yours, same discipline, prompts in the commits.</p>
</blockquote>
<h2>Where next 🎉</h2>
<p><strong>And the story continues:</strong> ClinicLive works — but it still looks like the template it was born from. Season two, <a href="https://www.coder000.com/post/ai-ui-design-escaping-the-slop">From Prompt to Polish</a>, redesigns it with AI: a real design system, four surfaces treated as four UX disciplines, and before/after screenshots of every step. Season three, <a href="https://www.coder000.com/post/maui-blazor-hybrid-companion-app-plan">From Prompt to Pocket</a>, then takes the same screens into a .NET MAUI app on Android and Windows — push notifications, haptics, a QR scanner and all.</p>
<p>Fourteen parts, one app, $6.20. If this series left you wanting to go deeper rather than wider: the <a href="https://www.coder000.com/post/blazor-tutorial-getting-started">Blazor series</a> builds the UI-side fundamentals this series moved fast over, and the <a href="https://www.coder000.com/post/sql-server-to-postgresql-why-switch">PostgreSQL series</a> gives the database the attention it deserved here. And if the commit-messages-as-prompt-log trick appealed to you, that only works when git is second nature — the <a href="https://www.coder000.com/post/git-history-why-version-control-exists">Git &amp; GitHub workshop</a> starts from the very beginning.</p>
<p>Got a war story — an app you built this way, a mistake <em>your</em> AI made that belongs in somebody's table? Tell me through the <a href="https://www.coder000.com/contact">contact page</a>. I read every message, and the best stories become posts.</p>
<p>The models in this series will be museum pieces in three years. The discipline won't: own the spec, read the diff, define correct, explain what you ship. The tools multiply judgment — so grow the judgment, and let them multiply it.</p>
<p>Thanks for building all fourteen parts with me. Now go build something of your own. 🤖</p>
<hr />
<p><em>Originally published at <a href="https://www.coder000.com/post/ai-development-cost-retrospective">coder000.com</a>. Part of the series <a href="https://www.coder000.com/series/from-prompt-to-production">From Prompt to Production</a> — read the whole series there.</em></p>
]]></content:encoded></item><item><title><![CDATA[AI-Assisted Development in 2026: Tools, Models and Honest Expectations]]></title><description><![CDATA[Over the next fourteen parts we're going to build one real application — a clinic booking-and-queue system with Blazor Server, PostgreSQL and SignalR — and an AI is going to write most of the code. We]]></description><link>https://coder000.hashnode.dev/ai-assisted-development-in-2026-tools-models-and-honest-expectations</link><guid isPermaLink="true">https://coder000.hashnode.dev/ai-assisted-development-in-2026-tools-models-and-honest-expectations</guid><category><![CDATA[AI]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[Blazor]]></category><category><![CDATA[claude]]></category><dc:creator><![CDATA[Rahul Vyas]]></dc:creator><pubDate>Mon, 07 Sep 2026 17:09:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6a9a1e06c4c50037751b6201/ce173896-93d4-4449-9112-ed20a36a8a49.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Over the next fourteen parts we're going to build one real application — a clinic booking-and-queue system with Blazor Server, PostgreSQL and SignalR — and an AI is going to write most of the code. We'll show every prompt, keep every mistake in, and count every dollar. This first part is the map: the tools, the models, and what you can honestly expect before we type a single prompt.</p>
<h2>Two ways to use AI for code</h2>
<p>If you've never used AI tooling, here's the landscape in one paragraph. The first way is <strong>chat</strong>: you open a chat window, paste some code, ask a question, and copy the answer back into your editor. It works — plenty of developers learned a lot this way — but notice who's doing the manual labour. The model only knows what you paste, it can't run anything, and <em>you</em> are the clipboard, ferrying code back and forth and hoping you pasted enough context.</p>
<p>The second way is <strong>agentic</strong>: a tool that lives in your project folder, reads your files itself, proposes edits as reviewable diffs, runs your build and your tests, and asks permission before doing anything. You stop being the clipboard and become the reviewer — which, as we'll see, is the job that actually matters.</p>
<p>This series uses <strong>Claude Code</strong>, Anthropic's agentic tool. It comes in whichever shape suits you: a command-line tool, a desktop app for Mac and Windows, a web version at claude.ai/code, and IDE extensions for VS Code and JetBrains. Everything in this series works the same in all of them; we'll set it up properly in <a href="https://www.coder000.com/post/claude-code-setup-for-dotnet">Part 2</a>.</p>
<h2>The method: prompt, review, refine, commit</h2>
<p>Before tools and prices, the thing that actually decides whether AI development goes well. Everything we build in this series follows one loop:</p>
<p><em>(diagram on the original post — the AI development loop: you write a prompt, the AI writes code, you review and test it; problems loop back into a refined prompt, good code gets committed.)</em></p>
<p>You describe what you want and why. The AI writes code you didn't type. Then comes the step that separates professionals from headlines: <strong>you read it, run it, and test it</strong>. Code that isn't right doesn't get argued with — it feeds a sharper, smaller prompt. Code that is right gets committed in a small, reviewable piece. That's the whole method. Every part of this series is this loop, applied to a different problem, and the review step is the one we never skip.</p>
<h2>Which model, when — and what it costs</h2>
<p>"AI" isn't one thing you talk to; you choose a model per task, and the choice is mostly about money and thinking depth. Models are priced per <em>token</em> — roughly three-quarters of a word — and you pay separately for what the model reads (input) and what it writes (output). Here's the current Claude line-up:</p>
<p><em>Claude models, August 2026 — prices per million tokens (input / output)</em></p>
<table>
<thead>
<tr>
<th>Model</th>
<th>Price in / out</th>
<th>What it's for</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Claude Opus 5</strong></td>
<td>\(5 / \)25</td>
<td>The deep-work default: hard design, debugging, code review</td>
</tr>
<tr>
<td><strong>Claude Sonnet 5</strong></td>
<td>\(3 / \)15</td>
<td>The everyday coding workhorse</td>
</tr>
<tr>
<td><strong>Claude Haiku 4.5</strong></td>
<td>\(1 / \)5</td>
<td>Quick questions and mechanical edits</td>
</tr>
</tbody></table>
<p>Each model also takes an <strong>effort</strong> setting, from low to max, which controls how hard it thinks before answering. High effort on a hard problem buys real quality; high effort on "rename this variable" buys you a more expensive rename. Our rule of thumb, which the whole series follows:</p>
<p><em>The rule of thumb this series lives by</em></p>
<table>
<thead>
<tr>
<th>The task</th>
<th>The pick</th>
<th>Because</th>
</tr>
</thead>
<tbody><tr>
<td>Writing a spec, designing a schema, reviewing code</td>
<td>Opus, high effort</td>
<td>Mistakes here compound for months; thinking is cheap by comparison</td>
</tr>
<tr>
<td>CRUD features, scaffolding, tests</td>
<td>Sonnet</td>
<td>Well-trodden ground; the workhorse handles it</td>
</tr>
<tr>
<td>"Rename this everywhere", formatting, tiny edits</td>
<td>Haiku</td>
<td>Mechanical work deserves mechanical prices</td>
</tr>
</tbody></table>
<blockquote>
<p>📝 <strong>Note:</strong> everything above is true <em>as of August 2026</em>. Models and prices churn faster than any other fact in this series — this is the one section you should re-check against current pricing before trusting the numbers. The <em>method</em> — match the model to the stakes of the task — outlives any price list.</p>
</blockquote>
<blockquote>
<p>🧠 <strong>Model pick:</strong> every part of this series opens its toolbox in a box like this one — which model, what effort, and why. This part is all reading, so nothing was billed to the build yet; the standing picks are the table above, and you'll see us follow it: Opus for the spec and schema in Parts 3–4, Sonnet for the scaffolding in Part 5.</p>
</blockquote>
<h2>Honest expectations</h2>
<p>Here's the part most AI content skips. These tools are genuinely, sometimes shockingly good at a specific set of things:</p>
<ul>
<li><strong>Boilerplate</strong> — the code you've written a hundred times and never enjoyed once: DTOs, mappings, configuration, test scaffolding.</li>
<li><strong>Translation between technologies</strong> — "this is how I did it in SQL Server, show me the PostgreSQL way" is a question AI answers better than most search results.</li>
<li><strong>First drafts</strong> — a working starting point in minutes, for you to shape.</li>
<li><strong>Explaining errors</strong> — paste a stack trace and get a plain-English account of what went wrong, and usually why.</li>
</ul>
<p>And there's a set of things it reliably gets wrong, no matter how impressive it looks while doing them:</p>
<ul>
<li><strong>Your business rules</strong> — the AI has never met your clinic, your users, or your edge cases. It will guess, confidently.</li>
<li><strong>Time zones</strong> — AI-written date handling that compiles and demos fine can still be quietly wrong about what "today" means. Ask us how we know (Part 10).</li>
<li><strong>Security defaults</strong> — it happily ships whatever a template ships, including the parts a hostile reviewer would circle in red (Part 11).</li>
<li><strong>Its own blind spots</strong> — it can't tell you what it doesn't know, and it repeats its habits. Wait until you see it make the exact same compiler error in two different parts.</li>
</ul>
<blockquote>
<p>🤖 <strong>What the AI got wrong:</strong> nothing yet — we haven't asked it for anything. But this box appears in every part, because keeping the mistakes in is the point of this series. Coming attractions, all real: an SMS feature nobody asked for (Part 3), timestamps without time zones (Part 4), a chat design that fails authentication forever (Part 8), and a test that passes <em>because</em> the code is wrong (Part 9). The human stays the pilot. That's not a disclaimer; it's the method.</p>
</blockquote>
<h2>What we're building: ClinicLive</h2>
<p>A real app needs a real problem, so meet <strong>ClinicLive</strong>: front-desk software for a small clinic. Patients book a 15-minute appointment from their phone — no account, no password, just a short confirmation code. A tablet at the door lets them check in with that code. A waiting-room screen updates by itself the second someone checks in. And behind the login, reception and practitioners see today's schedule, call the next patient, and chat with each other — with presence and typing indicators — instead of shouting down the corridor.</p>
<p><em>(diagram on the original post — ClinicLive architecture: the booking page, check-in kiosk and waiting-room board talk to the Blazor Server app; the QueueHub pushes live updates out; EF Core persists everything to PostgreSQL.)</em></p>
<p>That little diagram is the whole build: three browser surfaces, one Blazor Server app, one PostgreSQL database, and SignalR pushing changes out so nobody ever presses refresh. It's small enough to finish and real enough to hurt — bookings can race, queues can be ordered wrong, and time zones can lie. Perfect.</p>
<p>The finished code lives in the companion repository at <a href="https://github.com/rahulvyas777/clinic-live">github.com/rahulvyas777/clinic-live</a>, and it has one unusual property: <strong>every commit message contains the actual prompt that produced the commit</strong>. The repo's history <em>is</em> the series. From Part 3 onward there's a tag per part, so you can check out the code exactly as it stood at the end of any chapter.</p>
<h2>What about Copilot, Cursor and the rest?</h2>
<p>Alternatives absolutely exist — GitHub Copilot, Cursor, Google's Gemini CLI, and more arriving monthly — and they're good tools; the loop in the figure above applies to all of them. We use Claude Code for this series for an unexciting reason: going deep on one tool teaches you more than a survey of five, and depth is what you can carry to whichever tool your team ends up using. If your instinct is to comparison-shop first, our <a href="https://www.coder000.com/post/what-is-ai-assisted-coding">beginner's guide to AI-assisted coding</a> surveys the field; this series is the deep end.</p>
<blockquote>
<p>💸 <strong>The meter:</strong> our build so far: <strong>$0.00</strong>. Every part reports the running total, honestly. And a spoiler worth having up front: the entire fourteen-part build — spec, schema, features, real-time, tests, debugging, hardening and deployment — lands at about six dollars of model usage. Hold that number next to any hype you've heard, in either direction.</p>
</blockquote>
<blockquote>
<p>✅ <strong>Checkpoint:</strong> before Part 2 you should be able to say what separates chat from agentic tools, name which Claude model you'd pick for a schema design versus a mechanical rename, and sketch ClinicLive's three surfaces from memory. No installs yet — but having an Anthropic account ready (a paid Claude plan or API billing, either works) will make the next part a straight run.</p>
</blockquote>
<p>The map is drawn. In <a href="https://www.coder000.com/post/claude-code-setup-for-dotnet">Part 2</a>, Claude Code goes onto your machine, learns your project's house rules from a file called CLAUDE.md, and makes its first change to real code — reviewed, understood, and committed like you mean it.</p>
<hr />
<p><em>Originally published at <a href="https://www.coder000.com/post/ai-assisted-development-with-claude">coder000.com</a>. Part of the series <a href="https://www.coder000.com/series/from-prompt-to-production">From Prompt to Production</a> — read the whole series there.</em></p>
]]></content:encoded></item><item><title><![CDATA[What Building a Real App with AI Actually Cost: 36 Parts, Three Seasons, About $17]]></title><description><![CDATA[Three seasons, thirty-six parts, one clinic app — and a meter that ran the whole time. Every part of the ClinicLive trilogy ended with a 💸 box, every retro added its season up, and every number came ]]></description><link>https://coder000.hashnode.dev/what-building-a-real-app-with-ai-actually-cost-36-parts-three-seasons-about-17</link><guid isPermaLink="true">https://coder000.hashnode.dev/what-building-a-real-app-with-ai-actually-cost-36-parts-three-seasons-about-17</guid><category><![CDATA[AI]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[Blazor]]></category><category><![CDATA[Productivity]]></category><dc:creator><![CDATA[Rahul Vyas]]></dc:creator><pubDate>Fri, 04 Sep 2026 01:39:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6a9a1e06c4c50037751b6201/c82f182a-0774-415e-b13f-a1f53e2179f0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Three seasons, thirty-six parts, one clinic app — and a meter that ran the whole time. Every part of the ClinicLive trilogy ended with a 💸 box, every retro added its season up, and every number came from the build log rather than from memory. This post puts all of it in one place: what the whole thing cost, part by part and model by model, what caught the AI's mistakes, and what the money could not buy.</p>
<p><strong>About $17.</strong> Building ClinicLive with Claude Code cost ≈ $17.00 of API spend across 36 parts and three seasons: $6.20 for a shipped Blazor Server app, $3.60 for its redesign, and $7.20 for a .NET MAUI companion app on three hosts — with 28 tests green at the end and three public tag ranges in <a href="https://github.com/rahulvyas777/clinic-live">the repo</a> so you can check out any moment of it. One caveat before anything else, in the words of the footnote every retro carries: on a subscription plan your bill won't literally say $17 — but the tokens burned are the same, so it's the honest apples-to-apples number.</p>
<h2>The meter, all three seasons</h2>
<p>Here is every reading on one chart. The top row is what each part added; the bottom row is the trilogy's running total, which starts at forty cents for a spec and stops at seventeen dollars for a signed APK.</p>
<p><em>(chart on the original post — API spend per part across the three ClinicLive seasons, with the trilogy's running total underneath. Season one, 14 parts, $6.20; season two, 10 parts, $3.60; season three, 12 parts, $7.20. The running total climbs from $0.40 at season one's spec to \(17.00 at season three's ship-it part. The most expensive single reading is season three's Parts 1 and 2 together, at \)1.30.)</em></p>
<p>Three things jump out before any table. First, no part cost more than $1.30, and most cost less than a dollar — the tallest bars are the parts that opened a season, where the architecture decisions and a lot of screenshots happen at once. Second, the seasons are more alike than different: the redesign was the cheapest, but not by the margin "it's only CSS" would predict, because a model looking at screenshots is burning image tokens. Third, the dead ends are in there. Season one's failed first chat design, season three's Windows toast chase and its forty-minute hunt for a QR poster the emulator never drew — all billed at the same rate as the features, and all left in the number on purpose.</p>
<h2>Season by season</h2>
<p><em>What each season cost, and what it shipped</em></p>
<table>
<thead>
<tr>
<th>Season</th>
<th>Parts</th>
<th>Total</th>
<th>Per part</th>
<th>What shipped</th>
</tr>
</thead>
<tbody><tr>
<td><a href="https://www.coder000.com/post/ai-assisted-development-with-claude">One · From Prompt to Production</a></td>
<td>14</td>
<td>≈ $6.20</td>
<td>≈ $0.44</td>
<td>A Blazor Server app: PostgreSQL schema, booking, a live queue and board over SignalR, staff chat, nine tests against a real database, a hardening pass, an nginx and systemd deploy, CI (<code>part-03</code> to <code>part-12</code>)</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/ai-ui-design-escaping-the-slop">Two · From Prompt to Polish</a></td>
<td>10</td>
<td>≈ $3.60</td>
<td>≈ $0.36</td>
<td>A token-based design system with dark mode, Bootstrap deleted, four surfaces redesigned as four UX disciplines, an accessibility pass and a motion pass — nine tests still green (<code>polish-02</code> to <code>polish-09</code>)</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/maui-blazor-hybrid-companion-app-plan">Three · From Prompt to Pocket</a></td>
<td>12</td>
<td>≈ $7.20</td>
<td>≈ $0.60</td>
<td>A .NET MAUI Blazor Hybrid companion app on Android, Windows and the web: nine capability interfaces, a live queue, push, haptics, geolocation, a QR scanner, offline; a signed APK, a self-contained Windows build, CI — 28 tests (<code>pocket-02</code> to <code>pocket-11</code>)</td>
</tr>
<tr>
<td><strong>The trilogy</strong></td>
<td><strong>36</strong></td>
<td><strong>≈ $17.00</strong></td>
<td><strong>≈ $0.47</strong></td>
<td>One app, three seasons, everything above</td>
</tr>
</tbody></table>
<p>"Per part" divides by every part of a season, including the ones that built nothing — the intros, season one's power-moves tour, and the three retros. Divide by the parts that actually moved the meter and the numbers are $0.62, $0.40 and $0.72. Either way, the honest unit is "less than a coffee per part."</p>
<h2>Where the numbers come from</h2>
<p>Three retros, reconciled. <a href="https://www.coder000.com/post/ai-development-cost-retrospective">Season one's retro</a> lists a running total for each of Parts 3 to 12, and the build log agrees with it to the cent. <a href="https://www.coder000.com/post/ai-ui-design-retrospective">Season two's retro</a> merged Parts 1–2 and 3–4 into two rows because the log only recorded a reading at Parts 2 and 4; the per-part numbers for Parts 1 and 3 below ($0.40, then $1.30 on the running meter) come from those parts' own 💸 boxes, which the retro didn't repeat. <a href="https://www.coder000.com/post/maui-blazor-hybrid-retrospective">Season three's retro</a> has Part 1 riding inside Part 2's reading, because the plan had no commit and its smoke build landed in Part 2. Nothing here is a new measurement — it's the same 29 readings, laid end to end.</p>
<h2>Which model did what, and what the split cost</h2>
<p>Every part opened with a 🧠 box naming its model, and the rule never changed across three seasons: Opus where a mistake would compound — a spec, a schema, real-time semantics, a diagnosis, a review — and Sonnet where the path was well-worn: scaffolding, CRUD, tests, CSS, a documented toolchain. Here is how that rule played out, part by part, with what each part added to the meter.</p>
<p><em>Model per part across all 36 parts, and what each part added</em></p>
<p><strong>Season one · From Prompt to Production</strong></p>
<table>
<thead>
<tr>
<th>Part</th>
<th>What it built</th>
<th>Model</th>
<th>Why</th>
<th>Added</th>
</tr>
</thead>
<tbody><tr>
<td><a href="https://www.coder000.com/post/ai-assisted-development-with-claude">1</a></td>
<td>The landscape — reading, no build</td>
<td>—</td>
<td>Nothing billed</td>
<td>$0.00</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/claude-code-setup-for-dotnet">2</a></td>
<td>Claude Code setup, a two-line change</td>
<td>Sonnet</td>
<td>Everyday work</td>
<td>≈ $0</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/writing-a-software-spec-with-ai">3</a></td>
<td>The spec, nine clarifying questions</td>
<td>Opus</td>
<td>Decisions that compound</td>
<td>$0.40</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/designing-postgresql-schema-with-ai">4</a></td>
<td>PostgreSQL schema</td>
<td>Opus</td>
<td>Decisions that compound</td>
<td>$0.20</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/scaffolding-blazor-server-with-ai">5</a></td>
<td>Skeleton, entities, migration, seeder</td>
<td>Sonnet</td>
<td>Mechanical, well-trodden</td>
<td>$0.50</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/building-crud-features-with-ai">6</a></td>
<td>The booking flow</td>
<td>Sonnet</td>
<td>CRUD on a written spec</td>
<td>$0.70</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/signalr-live-updates-with-ai">7</a></td>
<td>Live queue: kiosk, board, SignalR hub</td>
<td>Opus</td>
<td>Real-time semantics</td>
<td>$0.90</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/blazor-server-chat-presence-signalr">8</a></td>
<td>Staff chat, presence, typing</td>
<td>Opus</td>
<td>One architectural judgment</td>
<td>$0.70</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/testing-ai-generated-code">9</a></td>
<td>Tests against a real PostgreSQL</td>
<td>Sonnet</td>
<td>Mechanical scaffolding</td>
<td>$0.70</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/debugging-with-ai">10</a></td>
<td>Two bug hunts</td>
<td>Opus</td>
<td>Diagnosis</td>
<td>$0.80</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/ai-code-review-security-pass">11</a></td>
<td>The hardening pass</td>
<td>Opus</td>
<td>Adversarial review</td>
<td>$0.70</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/deploying-blazor-signalr-vps">12</a></td>
<td>Runbook, nginx, systemd, CI</td>
<td>Sonnet</td>
<td>Documented territory</td>
<td>$0.60</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/advanced-ai-development-workflows">13</a></td>
<td>Power moves — built nothing</td>
<td>—</td>
<td>Nothing billed</td>
<td>—</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/ai-development-cost-retrospective">14</a></td>
<td>The retro</td>
<td>—</td>
<td>Nothing billed</td>
<td>—</td>
</tr>
</tbody></table>
<p><strong>Season two · From Prompt to Polish</strong></p>
<table>
<thead>
<tr>
<th>Part</th>
<th>What it built</th>
<th>Model</th>
<th>Why</th>
<th>Added</th>
</tr>
</thead>
<tbody><tr>
<td><a href="https://www.coder000.com/post/ai-ui-design-escaping-the-slop">1</a></td>
<td>Before shots, four directions, a veto</td>
<td>Opus</td>
<td>Divergence is a thinking task</td>
<td>$0.40</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/design-tokens-with-ai-blazor">2</a></td>
<td>Tokens, dark mode, Bootstrap deleted</td>
<td>Opus; Sonnet for the CSS</td>
<td>Structure and taste</td>
<td>$0.70</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/screenshot-loop-ai-design">3</a></td>
<td>The screenshot harness</td>
<td>Sonnet</td>
<td>Bread-and-butter code</td>
<td>$0.20</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/designing-booking-flow-phone-ux">4</a></td>
<td>Booking flow and the ticket</td>
<td>Sonnet</td>
<td>Execution on a settled system</td>
<td>$0.30</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/kiosk-touch-ux-design">5</a></td>
<td>Kiosk: code entry, success takeover</td>
<td>Sonnet</td>
<td>Execution on a settled system</td>
<td>$0.40</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/waiting-room-board-signage-ux">6</a></td>
<td>Board as signage</td>
<td>Opus</td>
<td>"What is this surface?"</td>
<td>$0.50</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/staff-pages-pro-tool-ux">7</a></td>
<td>Staff pages, the WAITED column</td>
<td>Sonnet</td>
<td>Execution on a settled system</td>
<td>$0.40</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/ai-accessibility-audit-blazor">8</a></td>
<td>Accessibility audit and fixes</td>
<td>Opus</td>
<td>Adversarial reading</td>
<td>$0.30</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/micro-interactions-css-blazor">9</a></td>
<td>Motion that explains change</td>
<td>Sonnet</td>
<td>Execution on settled rules</td>
<td>$0.40</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/ai-ui-design-retrospective">10</a></td>
<td>The retro</td>
<td>—</td>
<td>Nothing billed</td>
<td>—</td>
</tr>
</tbody></table>
<p><strong>Season three · From Prompt to Pocket</strong></p>
<table>
<thead>
<tr>
<th>Part</th>
<th>What it built</th>
<th>Model</th>
<th>Why</th>
<th>Added</th>
</tr>
</thead>
<tbody><tr>
<td><a href="https://www.coder000.com/post/maui-blazor-hybrid-companion-app-plan">1</a></td>
<td>The plan and a smoke build</td>
<td>—</td>
<td>Rides inside Part 2</td>
<td>—</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/maui-blazor-hybrid-shared-ui-three-hosts">2</a></td>
<td>Contracts, shared RCL, two hosts, insets</td>
<td>Opus; Sonnet for the stylesheet</td>
<td>Architecture and a diagnosis</td>
<td>$1.30 (with Part 1)</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/maui-app-api-for-blazor-server-backend">3</a></td>
<td>The API, the client, the Visit screen</td>
<td>Sonnet; Opus for one call</td>
<td>Plumbing on settled rules</td>
<td>$0.60</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/signalr-in-maui-blazor-hybrid">4</a></td>
<td>SignalR on the phone, lifecycle, reconnect</td>
<td>Opus; Sonnet for the page</td>
<td>Connection semantics</td>
<td>$0.70</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/maui-haptics-local-notifications">5</a></td>
<td>Haptics, notifications, the Windows dead end</td>
<td>Opus; Sonnet for the platform bodies</td>
<td>Product decisions</td>
<td>$0.80</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/firebase-push-notifications-maui-android">6</a></td>
<td>Firebase push to a closed app</td>
<td>Opus; Sonnet for the bindings</td>
<td>Stopped-state semantics</td>
<td>$0.80</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/maui-geolocation-maps">7</a></td>
<td>Geolocation and maps</td>
<td>Sonnet; Opus for two things</td>
<td>Essentials did the work</td>
<td>$0.50</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/maui-qr-scanner-zxing-blazor-hybrid">8</a></td>
<td>QR on the ticket, the native scanner</td>
<td>Opus for two judgments; Sonnet for the rest</td>
<td>A native page over the WebView</td>
<td>$0.90</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/maui-offline-preferences-securestorage">9</a></td>
<td>Connectivity, two-tier storage, the cached visit</td>
<td>Sonnet; Opus for two decisions</td>
<td>Plumbing</td>
<td>$0.50</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/maui-blazor-hybrid-windows-desktop">10</a></td>
<td>A desk-sized window, one breakpoint</td>
<td>Sonnet</td>
<td>CSS and a window size</td>
<td>$0.40</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/maui-release-build-signing-ci">11</a></td>
<td>Signed Android, Windows publish, CI</td>
<td>Sonnet; Opus for what not to fake</td>
<td>Toolchain plumbing</td>
<td>$0.70</td>
</tr>
<tr>
<td><a href="https://www.coder000.com/post/maui-blazor-hybrid-retrospective">12</a></td>
<td>The retro</td>
<td>—</td>
<td>Nothing billed</td>
<td>—</td>
</tr>
</tbody></table>
<p>Add it up by lead model and the split is even in count and uneven in cost. <strong>Fifteen Opus-led parts cost $10.10</strong>, about $0.67 each. <strong>Fifteen Sonnet-led parts cost $6.90</strong>, about $0.46 each — $0.49 if you leave out season one's setup part, which cost effectively nothing. Six parts have no reading of their own. So the thinking model's parts cost about half as much again, and less of that gap than you'd guess is the price list: the Opus parts were also the ones with the long design conversations, the failed first attempts and the most screenshots.</p>
<p>One honesty note about that arithmetic. The log records one reading per part, not one per model. Where a part used both — most of season three did — the whole reading is counted under the model its 🧠 box leads with, the one that made the part's defining call. That is a judgment, and season three's scanner part is the closest one.</p>
<blockquote>
<p>🧠 <strong>The rule, unchanged for 36 parts:</strong> match the spend to the consequence of error, not to the difficulty of the typing. Season one put it as "where mistakes compound"; season two as "what <em>is</em> this surface?"; season three as "semantics — foreground versus background versus stopped." Same rule, three axes. It never needed revising, and the table above is the receipt.</p>
</blockquote>
<h2>What caught the AI's mistakes</h2>
<p>The three retros keep a mistake table each: eight rows holding 14 mistakes for season one, 6 for season two, and 44 rows for season three, one of which is an honest "no code catch" rather than a mistake. The later two tables record what caught each one; season one's has no such column, so its 14 are classified here from the descriptions. Tallied together:</p>
<p><em>What caught each of the 63 logged mistakes, by season</em></p>
<table>
<thead>
<tr>
<th>Caught by</th>
<th>Season one</th>
<th>Season two</th>
<th>Season three</th>
<th>Total</th>
</tr>
</thead>
<tbody><tr>
<td>A screenshot</td>
<td>0</td>
<td>5</td>
<td>16</td>
<td><strong>21</strong></td>
</tr>
<tr>
<td>A human reading or looking</td>
<td>9</td>
<td>1</td>
<td>9</td>
<td><strong>19</strong></td>
</tr>
<tr>
<td>The compiler or a failing build</td>
<td>2</td>
<td>0</td>
<td>8</td>
<td><strong>10</strong></td>
</tr>
<tr>
<td>Running it: the app, a log, the emulator</td>
<td>2</td>
<td>0</td>
<td>6</td>
<td><strong>8</strong></td>
</tr>
<tr>
<td>A test</td>
<td>1</td>
<td>0</td>
<td>3</td>
<td><strong>4</strong></td>
</tr>
<tr>
<td>CI</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td><strong>1</strong></td>
</tr>
<tr>
<td><strong>Mistakes logged</strong></td>
<td><strong>14</strong></td>
<td><strong>6</strong></td>
<td><strong>43</strong></td>
<td><strong>63</strong></td>
</tr>
</tbody></table>
<p>The honest reading is that the tools people assume catch AI mistakes caught the fewest. The compiler and the build found ten of sixty-three, and most were fixed in minutes — <code>CS0542</code> twice, an ambiguous <code>View</code>, a DLL lock, a runtime pack that doesn't exist. Tests found four, and three of those were the test being wrong rather than the code. The two catchers that found forty of the sixty-three were a screenshot and a person. The screenshot loop found a sidebar on a TV, an error banner on every page, a status bar the wrong color, a phone that had quietly given up reconnecting — things no diff can show. A person found the rest, from a spec that invented SMS, to a palette that was a near-twin of the author's other project, to a captured desktop that should never have been captured. Season one's shape is different for a reason: with no screenshot loop yet, its catches came from reading code against a spec, which is why "a human" carries nine of its fourteen.</p>
<p>Two fairness notes. Tests look weak in this tally and were the strongest thing in the trilogy: the nine written in season one stayed green through a redesign that touched every page, and the 28 at the end are why a phone, a desk and a browser could share one set of rules without anyone re-checking them by hand. Catching mistakes and preventing them are different jobs. And nothing in the table was free: screenshots are image tokens, and the person is not on the meter at all — which is the next section.</p>
<h2>What the money did not buy</h2>
<p><strong>Human time is not on the meter.</strong> Say it plainly, because the $17 headline invites the wrong conclusion. The meter counts tokens; it does not count reading every diff before accepting it, pasting a schema into a review, judging four art directions, vetoing a palette, toggling airplane mode, reading a vibrator log, or looking at a screenshot before writing its caption. Season one estimated its own wall-clock at roughly an hour of AI-assisted building against two to three days by hand — and even that hour sits beside the review time the retro called "the real cost," like the twenty minutes of human reading that <a href="https://www.coder000.com/post/scaffolding-blazor-server-with-ai">Part 5</a> said was the most expensive thing in it. Seasons two and three never logged hours at all; their retros say where the time went instead: "most of it is the looking," and "the meter bought code; the proving is where the season went." If you want a real cost per part, add your own hours to the $0.47.</p>
<p><strong>The bench.</strong> An Android emulator, a Windows desktop, a free-tier Firebase project, a PostgreSQL in Testcontainers, a Playwright harness that photographs every surface, and a screenshot script that learned — the hard way, twice — to refuse a frame it doesn't own. None of that is a token, and season three's retro is clear that the bench, not the model, is where that season went.</p>
<p><strong>Three things the bench couldn't prove.</strong> Windows toast notifications never displayed: registration succeeds, the setting says Enabled, and no banner appears, because an unpackaged app has no identity and the series declined to fake an MSIX. No on-device QR decode was photographed, because the emulator never rendered its posters; the chain is proven by a test instead — everything except the lens. And Google Maps launched and crashed on the emulator after the directions intent resolved. Season three's retro keeps all three together, and $7.20 closed none of them.</p>
<p><strong>What was never built.</strong> iOS compiles and was never built, for want of a Mac. Patient accounts and SMS, which the spec said no to in Part 3 and kept saying no to. A packaged Windows build. Anything a real phone does after the emulator's Maps died.</p>
<p><strong>The judgment.</strong> The most valuable lines in the trilogy were typed by a person before the model started, and cost nothing: the spec's non-goals; the rule that a test is written from the spec, never from the code; "who uses this surface, and what state do they find it in?"; "a second front door must not grow a second set of rules"; "stale means read-only"; "fake nothing." Each would have shipped as something plausible and worse without it. The dollars bought drafts; those sentences are why the drafts became an app.</p>
<h2>How the meter is measured</h2>
<p>Every retro carries the same footnote under its bill, with its own season's number in it. Here it is exactly as season three's retro prints it — the 🧠 boxes it refers to are the per-part model picks summarized in the table above:</p>
<p><em>How the meter is measured: the build's actual token consumption priced at the API list rates of the models used (the 🧠 boxes name them). On a subscription plan your bill won't literally say $7.20 — but the tokens burned are the same, so it's the honest apples-to-apples number.</em></p>
<p>Two details that follow from it. The tokens include every image the model looked at, which is why screenshot-heavy parts cost more than their code would suggest. And every reading was written down at ten-cent precision as its part landed, which is why every number in this post wears a ≈.</p>
<h2>Frequently asked</h2>
<p><strong>How much does it cost to build an app with Claude Code?</strong></p>
<p>For ClinicLive it was about $17 of API spend across 36 parts: $6.20 for a Blazor Server app with PostgreSQL, SignalR and tests, $3.60 for a complete redesign, and $7.20 for a .NET MAUI companion app on Android, Windows and the web. That is actual token consumption priced at API list rates; the human time spent reviewing and testing is not included.</p>
<p><strong>Is Opus or Sonnet cheaper for AI-assisted development?</strong></p>
<p>In this build the fifteen Sonnet-led parts averaged about \(0.46 each and the fifteen Opus-led parts about \)0.67, but the choice was made by consequence of error, not price: Opus for specs, schemas, real-time semantics, diagnosis and reviews; Sonnet for scaffolding, CRUD, tests, CSS and documented toolchains.</p>
<p><strong>What catches the mistakes in AI-generated code?</strong></p>
<p>Across 63 logged mistakes in three seasons, screenshots caught 21, a human reading or looking caught 19, the compiler or a failing build caught 10, running the app caught 8, tests caught 4 and CI caught 1. The compiler and tests are necessary, but most of the catching was done by looking at the running result and by a person.</p>
<p><strong>What does the $17 not include?</strong></p>
<p>Human time: reading every diff, reviewing screenshots, running an emulator and a device bench, and deciding what correct means. It also leaves out the hardware and accounts used, three things the bench could not prove, and an iOS build that was never made.</p>
<p>If you want the stories behind the numbers, the three retros have them: <a href="https://www.coder000.com/post/ai-development-cost-retrospective">what ClinicLive really cost</a>, <a href="https://www.coder000.com/post/ai-ui-design-retrospective">what a redesign really costs</a>, and <a href="https://www.coder000.com/post/maui-blazor-hybrid-retrospective">what a companion app really costs</a>. And each season starts where its Part 1 does: <a href="https://www.coder000.com/post/ai-assisted-development-with-claude">From Prompt to Production</a>, <a href="https://www.coder000.com/post/ai-ui-design-escaping-the-slop">From Prompt to Polish</a>, and <a href="https://www.coder000.com/post/maui-blazor-hybrid-companion-app-plan">From Prompt to Pocket</a>. Thirty-six parts, one app, about seventeen dollars — and a great deal of looking that no meter ever saw.</p>
<hr />
<p><em>Originally published at <a href="https://www.coder000.com/post/what-building-a-real-app-with-ai-actually-cost">coder000.com</a>. It sums up the ClinicLive trilogy — <a href="https://www.coder000.com/series/from-prompt-to-production">From Prompt to Production</a>, <a href="https://www.coder000.com/series/from-prompt-to-polish">From Prompt to Polish</a> and <a href="https://www.coder000.com/series/from-prompt-to-pocket">From Prompt to Pocket</a> — read the whole series there.</em></p>
]]></content:encoded></item></channel></rss>