I’ve written before about building River, a “home-cooked meal” of an app for my family. Then tillerBuddy. Each one was fun to build and useful. But each one also took days of work — wrestling with CloudKit, vibe coding against Google Sheets, iterating on SwiftUI views.

After the third or fourth app, I noticed I was doing the same dance every time. Stand up a database. Wire up realtime sync. Generate SwiftUI CRUD views. Build. Sign. Archive. Upload. Wait for TestFlight processing. Register an MCP server so Claude can manage the data too. Naturally, I used Claude to do much of the tedious work, but some was still click-ops that just isn’t that fun for me. What if I could automate away that un-fun part?

The Dark Factory#

There’s a concept in manufacturing called a “dark factory” — a facility so automated that it runs with the lights off. No humans on the floor. I liked the metaphor, even if mine still needs a human for a couple of steps. Call it a dim factory. Or like turning on the lights at Space Mountain - you just don’t do it much; it looks weird in there and ruins the illusion.

The iOS App Factory is a Claude skill. I type something like:

/ios-app-factory Make me an app to track TV shows my family wants to watch. Use TMDB for metadata and poster images.

Thirteen minutes later, I have:

  1. A Supabase backend — Postgres schema, tables, row-level security, realtime enabled
  2. A working iOS app on TestFlight, installable on every family phone
  3. An MCP server backed by the same Supabase tables, so Claude can manage the data conversationally

That’s the whole trick. One sentence in, three artifacts out. The MCP part is what makes it more than just an app generator — Claude can now say “add milk, eggs, and bread to the grocery list” and it lands in the same database the iOS app reads from. The iOS app gets a realtime push and updates instantly. Two interfaces to the same data: one for tapping, one for talking.

What It’s Built#

So far the factory has produced:

  • TV Tracker — TMDB-powered show tracker with poster grids, status filtering, ratings. The most visually complex one.
  • Trip Planner — Trips with flights, ground transport, daily itineraries, and notes. Four entities, nested navigation.
  • Family Todos — Shared to-do lists. The simplest one, first out of the factory. To be honest, it’s not its best work, and probably won’t be used.

Plus a few more that I built during development to validate the whole pipeline. Each of these apps shares one Supabase project — separate Postgres schemas keep them isolated, but they all run on a single free-tier instance. Each gets its own MCP edge function on Supabase, its own set of CRUD tools that Claude sees as native capabilities.

How It Works (Briefly)#

The factory is a Claude Code skill — a structured prompt that tells Claude how to execute a multi-step pipeline. When I invoke it, here’s roughly what happens:

  1. Claude asks me a couple of clarifying questions about the data model
  2. Provisions the Supabase schema — CREATE SCHEMA, tables, grants, RLS, realtime publication
  3. Generates and deploys an MCP edge function (Deno + Hono + the MCP SDK) with CRUD tools for each entity
  4. Registers that MCP server in Claude’s settings so it’s available in all future conversations
  5. Generates a complete Xcode project from scratch — Swift models, SwiftUI views, Supabase realtime subscriptions
  6. Builds it, fixes any compilation errors, rebuilds
  7. Archives, signs, and uploads to TestFlight

Steps 2 through 7 are fully automated. Claude reads build errors, edits the code, and retries. It typically self-corrects within a couple of attempts.

The architecture is intentionally boring. One SPM dependency (the Supabase Swift SDK). xcodegen for deterministic project generation. xcodebuild for everything build-related. The asc CLI for App Store Connect API calls. No Fastlane — it can’t do headless auth, which is a dealbreaker for automation.

The Flaws#

It’s not perfect. Three things I haven’t solved:

The one manual step. Apple’s App Store Connect API, despite being otherwise comprehensive, does not support creating app records. It’s a platform limitation — affects everyone, not just my setup. So for each new app, I have to run one interactive command that requires my Apple ID password and 2FA. Takes about 30 seconds. After that, everything else is headless.

Xcode’s amnesia. Xcode periodically forgets my App Store Connect identity. I’ll go to deploy an app after a few days and the archive step fails because Xcode can’t find my logged-in developer account. The fix is to open Xcode, go to Settings → Accounts, and re-authenticate.

The UI is… fine. Claude generates functional apps. Everything works — lists scroll, forms validate, realtime syncs, navigation flows make sense. But nobody’s going to screenshot these apps and post them on Dribbble. The layouts are competent but generic. No visual personality. The iPad layout looks like a stretched iPhone app (a cardinal sin in my book - this isn’t an Android app!) For home-cooked apps with an audience of four, this is kinda acceptable. Though it does still offend my senses, and feels like the first improvement I’ll make to the factory. It’s the most obvious gap between what the factory produces and what a human designer would create.

Dates are hard There are endless date-math bugs in deployed sofware, and my factory makes them too! Especially bad in the Travel app, dates were off by one day because of ambiguity of time zone: half my code assumed GMT, half assumed PDT. Fun times.

The 13-Minute Thing#

It’s kind-of amazing to me that the thirteen minutes from prompt to TestFlight download is real. In the early days of the App Store, I spent days fighting signing tools. Overhead that took away from my creative time. This amazingly short time breaks down roughly like:

  • ~2 minutes: Claude asks questions, provisions Supabase, deploys MCP
  • ~4 minutes: Code generation, first build, fix compilation errors, rebuild
  • ~2 minutes: Archive, sign, upload to App Store Connect
  • ~5 minutes: Apple’s TestFlight processing (this is Apple’s queue, not mine)

The processing time is the annoying part because it’s just waiting. But I can install the build on my phone 13 minutes after typing a sentence. That still amazes me, even after doing it several times.

Why This Matters (To Me)#

Robin Sloan wrote about apps as home-cooked meals. That idea stuck with me and directly led to River. But River took weeks. tillerBuddy took days. Now I’m producing apps in minutes.

This isn’t a startup idea. I’m not building the next low-code platform. The factory is tuned to my family’s needs: we share one Supabase project, we trust each other (no authentication), we all have iPhones. My app embeds a supabase key (gasp!). The RLS policy on every table would make a security auditor faint.

But that’s the point. Home-cooked meals don’t need health inspections. I know what’s in the food. I know who’s eating it. And now I have a kitchen that’s pretty fast. Any threat model would be “the call is coming from inside the house”. I’d have bigger problems.

The interesting shift is going from “I could build an app for that” to “I will build an app for that, right now, before dinner.”