Since I was a kid, I’ve wanted to build a product that people use every day. The movie The Social Network, which tells the story behind Facebook, lit that entrepreneurial spark, and it’s why I studied Computer Science: I wanted the ability to build technology products. But shipping a full iOS app always felt out of reach. The workload, the time, and my level of Swift were never enough to make me feel comfortable starting.
I shipped one anyway, in days rather than years. The trick was treating Claude not as autocomplete, but as the engineer doing the heavy lifting while I played product owner. Here’s how it went.
The idea: exclusivity as a feature
A few years ago my friends introduced me to a dating app called RAYA. The concept stood out from everything else in the category. To join, you apply, get referred by your contacts, and wait for approval. The promise: mostly creatives, high-net-worth individuals, and models get in. That exclusivity fascinated me. It’s the same lever luxury brands pull (think Rolex and its waiting list): cut supply to create demand.
After a few years living in the Eastern Suburbs of Sydney, I saw how powerful a tight local community can be. So I pictured a RAYA built only for Bondi Beach and the Eastern Suburbs. The people here are young, often expats, looking to connect with people like them. Sarcastic local Instagram pages already thrive (doublebaytoday, overheardpaddington), so the community exists and loves content that feels like home. A niche this tight spreads by word of mouth, which means virality without burning cash on ads.
I called it Club BONDI.


Choosing the stack, with one non-obvious criterion
First the language. I chose Swift, which keeps the app iOS and App Store only at launch. That suits me, because that’s exactly where my audience is.
Then the backend, where I added a criterion most people skip: does it have an MCP integration?
The Model Context Protocol (MCP) is an open standard that lets Claude connect straight to an external system (a database, an API, a tool) and operate it, with no copy-pasting from me. When a platform speaks MCP, Claude inspects the schema, runs queries, changes security rules, and debugs the backend itself. The backend stops being a thing I babysit and becomes a thing Claude builds alongside the app. Supabase (Postgres, Auth, Realtime, Storage) ships a clean MCP integration and proved easy to use, so it was the obvious pick.
My final stack:
- Coding language: Swift, the native language for iOS
- Backend / database: Supabase, Postgres with an MCP integration
- SMS verification: Twilio, which sends the one-time codes that confirm a real phone number at sign-up. That matters for an invite-only app, where bots and fake accounts would break the whole premise.
- IDE / compiler: Xcode, native to iOS

What Claude Code actually is
Claude Code is not a chatbot in a browser tab. It’s an agentic coding tool that runs in my terminal. It reads and writes the files in my project, runs commands, searches the codebase, and reaches into Supabase over MCP. I describe what I want in plain English; it edits real files on my machine and reports back what it changed. I stay the product owner. Claude does the engineering.

Defining the product: KISS and a screenshot loop
With the stack ready, I had to decide exactly what to build. I followed the KISS principle, Keep It Simple, Stupid. I downloaded RAYA, walked through its sign-up, and screenshotted every screen.
Then I worked a tight feedback loop:
- Paste a RAYA screenshot into Claude and describe the screen I wanted.
- Claude generates the SwiftUI.
- I run it in Xcode and look at the result.
- I screenshot my version and tell Claude what’s off: “make the heading a serif font,” “the button should be a white capsule,” “tighten the spacing.”
- Claude adjusts. Repeat until it matches.
Because Supabase talked to Claude over MCP, the backend grew alongside the interface. As Claude laid out a profile screen, it also created the matching Postgres table and the security rules behind it. Front end and back end moved together, instead of one waiting on the other.

Giving Claude a memory: the CLAUDE.md file
The biggest upgrade to my workflow was a CLAUDE.md file. It sits at the root of the project, and Claude Code reads it automatically at the start of every conversation. It’s the project’s memory. Instead of re-explaining everything each time I open a new chat, Claude already knows the context.
Mine captures what the app is, the brand, and the rules of the codebase. A few real lines:
## Brand & design language
Dark-theme-first, modelled on the Raya aesthetic. Always use the tokens and
components in BondiTheme.swift. Never hardcode colors, fonts, or button styles.
- Canvas is black; cards are near-black greys.
- Headings are serif; body is sans; buttons are capsules.
## House rules for Claude
- When changing data shape, update the Swift model, the Postgres table/view,
and the RLS policy together. They're a set.
- Phone numbers are always E.164 (+61...).
- Keep it simple (KISS). Prefer the smallest change that ships.
The payoff is consistency. Every session reads the same brand and architecture rules, so Club BONDI ended up with one coherent design language, a single BondiTheme file driving colors, fonts, and capsule buttons across dozens of screens. No drift, even though I built it one screen at a time.

The parts that would have stopped me cold
This is where building with Claude stopped feeling like a toy and started feeling like leverage. Several features are exactly the kind of work that would have cost me weeks of Stack Overflow on my own, and Claude scaffolded them correctly:
- An image cache for profile photos. Dating apps live and die on photos. Rather than load full-resolution images and burn through memory, Claude wrote a cache that downsamples images as they decode, deduplicates requests for the same photo, and caps memory use. I didn’t know that was a problem until I had the solution.
- Subscriptions with StoreKit 2. The app runs a monthly subscription. Claude built the purchase flow, the “restore purchases” path, and synced the subscription status back into Supabase so the rest of the app reads it quickly, while keeping Apple as the source of truth.
- Real-time chat. Messages arrive live over Supabase’s real-time channel, fetching only new messages and skipping duplicates. You can even “like” a single message.
- The vetting flow. The apply, get-reviewed, approved-or-rejected journey that makes the app exclusive is its own state machine, capped by a “decision gate” screen that reveals your result. The concept from the intro, turned into working screens.

Where it got hard
“I built an app in a few days” can sound like there was no friction. There was.
StoreKit showed the limits of an agent. Claude wrote all the subscription code cleanly. But to use Apple’s StoreKit and the Supabase SDK, you have to add them as package dependencies inside Xcode, a few clicks in Xcode’s Swift Package Manager GUI. Claude writes files and runs terminal commands, but it can’t click around inside Xcode’s interface, so that step fell to me. It marked a clear boundary: Claude does the engineering, but some IDE setup stays a human job.
Auth took several tries to describe. The sign-in flow was the trickiest logic. A returning user who already applied should land somewhere different from a brand-new applicant, even though both just verified the same phone number. That wasn’t a coding problem so much as a describing problem. I walked Claude through the user journey in plain English several times (“if they already have an application, send them to check their status; if not, send them to apply”) before the state machine behaved. The lesson: the quality of what you get out tracks the clarity of what you put in.

Putting agents to work: testing and deploying
Two repeatable jobs became their own agents — specialized Claude configurations, each a small file with its own instructions, its own set of tools, and even its own model. An agent is just Claude pointed at one recurring task and told exactly how I want it done, so I can hand off the whole job in a sentence instead of re-explaining it every time. I built two: one to test, one to ship.
The UAT agent
The first is a UAT (User Acceptance Testing) agent. Before each release it does what I’d otherwise be doing by hand at midnight: it runs through the app like a real user, hunts for critical bugs, and fixes them on the spot. It runs on Opus, Claude’s most capable model, because the flows it has to reason through are multi-step — apply, get approved, pay, build a profile, swipe, match, chat — and a lighter model loses the thread halfway down.
Concretely, it does three things. It writes a test plan: concrete, checkable cases for every key flow, including the awkward edge rules that are easy to forget — “an approved user who hasn’t finished their profile must not be able to see anyone else,” or “re-passing someone you already passed should be a silent no-op, not an error.” Then it drives the running app in the iOS Simulator, walking each case and screenshotting the screen as evidence of pass or fail. Finally it checks the backend: because Supabase speaks MCP, the agent reads the database directly to confirm the data actually landed the way the screens implied — that the application row has the right status, that a “like” recorded the exact photo it should have, that a blocked user really disappears from the feed.
A couple of real-world wrinkles had to be solved for it to run unattended. Phone sign-in normally texts you a one-time code, and no agent can read an SMS — so I added a handful of test phone numbers in Supabase with fixed codes, used only for testing, that skip the real text. Subscriptions are similar: a local StoreKit configuration lets the agent exercise the paywall in the simulator without a real Apple purchase. And when it does find a critical bug, it follows the same house rules in CLAUDE.md that I do — fix the Swift model, the database table, and the security policy together — then re-runs the failing case to prove the fix took.

The deployment agent
The second is a deployment agent, and it kills the most tedious chore in the project: getting a fresh build into testers’ hands. By hand that’s a sequence of fiddly, easy-to-botch steps — bump the build number, archive the app, sign it, export it, upload it. The agent runs the whole pipeline from a single instruction: it archives the app, exports a signed build, and uploads it to App Store Connect, where it appears in TestFlight for my beta testers a few minutes later. It can even invite new testers by email. It authenticates with an App Store Connect API key rather than my Apple password, and stamps every upload with a fresh build number so Apple never rejects a duplicate.
I deliberately drew its boundary at TestFlight. Pushing a beta to testers is safe and reversible; submitting to the public App Store is not, so that final button stays mine to press. It’s the same principle as the StoreKit setup earlier — Claude does the engineering, and the irreversible, outward-facing calls stay with me. Either way, shipping a new beta went from a fiddly manual chore to a few seconds of work.

What I took away
Building Club BONDI changed how I think about creativity and software.
The barriers to building an idea are collapsing. Work that would have taken a year of full-time effort a few years ago, I put together in days. When building gets that cheap, the bottleneck stops being engineering and becomes taste: knowing what to build and describing it clearly.
Hyper-targeted apps for specific communities, like Club BONDI, will become far more common. They personalize the experience, and they reach a market without spending millions, because the community handles the distribution.
Longer term, the way we use apps will change. The underlying services will still exist, but we’ll reach them through assistants like Claude and ChatGPT, over protocols like MCP. The assistant becomes the main interface, rendering whatever the moment calls for. The app as a fixed set of screens may be the thing we look back on as old-fashioned.
Either way, the takeaway from Club BONDI is simple: the ideas you’ve shelved because they felt too hard to build are far closer than they used to be.

