> ## Documentation Index
> Fetch the complete documentation index at: https://docs.modaal.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Choosing the Right iOS Architecture: MVVM or RIBs?

> A Practical Guide with Case Studies

## Introduction

You describe an app idea to an AI agent, and it starts generating code. A few hours later — a working prototype. A few days later — a full-featured app with a dozen screens. But how manageable will that app be when it grows? That depends on the architecture the agent lays down at the start.

The iOS ecosystem has plenty of architectural patterns: MVVM, VIPER, Clean Architecture, TCA (The Composable Architecture), RIBs, MVVM+C, and more. Each has its strengths. Modaal currently supports two of them — and that's a deliberate choice, not a limitation:

* **MVVM** (Model-View-ViewModel) — a lightweight architecture on pure SwiftUI. Minimal ceremony, fast start. You and the AI agent produce a working prototype in hours.
* **RIBs** (Router-Interactor-Builder, via CombineRIBs) — a production architecture for long-lived projects. Clear module boundaries, an explicit navigation tree, structural contracts. The AI agent assembles a full app in days.

These two architectures cover opposite ends of the spectrum — from a quick prototype to a scalable production app. Support for TCA and potentially other patterns will come as demand warrants.

For watchOS, there's also **MV** (Model-View) — a simplified variant of MVVM.

The one rule to internalize before reading further: **migrating from MVVM to RIBs is a full rewrite**, not a refactor. That's fine if you know it upfront. It's a disaster if you find out later.

***

## How the Decision Tree Works

Before diving into case studies, it helps to understand the selection logic. It's simple — one key question, then refinements.

### Step 1. Is This a Prototype or a Production App?

If the project is an idea validation, an investor demo, or a personal utility — go with **MVVM**. You and the AI agent will generate a working app in a few hours. SwiftUI + `@Observable` + `NavigationStack` — and you've already got reactive state, native navigation, and testable ViewModels.

If the project will live long, grow past a dozen screens, or eventually ship on Android — go with **RIBs**. Even with RIBs, the agent delivers a complete app in days, not weeks — the time difference is smaller than you might think.

### Step 2. Additional Signals Favoring RIBs

* Cross-platform parity needed (iOS + Android)
* Heavy UIKit integration (camera, video, custom view controllers)
* Complex hierarchical navigation with deep linking
* Regulated industry (fintech, healthtech) — clear module boundaries required
* The project will grow and accumulate features over time

### Step 3. The Honest Conversation

Before picking MVVM for a project that "might eventually go to production," ask yourself: "Am I ready to rewrite everything from scratch when that day comes?" If the answer is "probably not" or "I hadn't thought about that" — you're probably better off starting with RIBs.

***

## Case Study 1. Workout Interval Timer

### Context

Max wants to build a simple interval training app. Three screens: a list of workout templates, interval settings, and the timer screen itself with start / pause / stop buttons. It's a personal project, maybe he'll share it with friends. No cloud anything — data stored locally in SwiftData.

### Applying the Decision Tree

**Step 1: Prototype or production?** — This is a personal utility. Even if Max puts it on the App Store, it's unlikely to grow to 50 screens. Clearly a prototype/utility.

**Additional signals:** No Android plans, three screens, linear navigation (list → settings → timer). Not a single signal points toward RIBs.

### Decision: MVVM

The architectural overhead of RIBs isn't justified here. Builder, Router, Interactor, Component — for three screens, that's unnecessary scaffolding. MVVM gives everything needed:

* `TimerViewModel` with `@Observable` holds the timer state
* `NavigationStack` with `NavigationLink` and `.sheet()` — that's all the navigation
* `@Environment` for injecting the data persistence service
* Tests written against the ViewModel with zero navigation mocks

Max describes the idea to the agent — and a few hours later has a working MVP. If he later wants to add a WidgetKit widget or an Apple Watch companion — MVVM won't get in the way, since those targets also run on pure SwiftUI.

### Takeaway

For apps with 3–10 screens and a clear, bounded scope, MVVM is the right call. Don't "play it safe" with a heavier architecture just in case.

***

## Case Study 2. Mobile Banking

### Context

A fintech company is building a mobile bank. Requirements include: registration with KYC verification, a home screen with balances, money transfers (P2P and IBAN), transaction history with filters, profile settings, push notifications, biometric authentication. Android is planned in 6 months.

### Applying the Decision Tree

**Step 1: Prototype or production?** — Production, no question. This is a regulated industry — the app handles real money. There's no "throwaway" here.

**Additional signals:**

* *Android:* Planned in 6 months. RIBs exists on both platforms with identical semantics. The iOS RIB tree becomes a 1:1 blueprint for Android — modules can be ported incrementally.
* *Navigation:* KYC verification is a multi-step flow with branches (document photo → selfie → verification → waiting → result with possible back-navigation). Money transfer is another flow with an auth gate. RIBs models these as a router tree: attach → detach, and you always know where the user is.
* *Security:* Fintech demands clear module boundaries. RIBs provides Builder/Component boundaries — explicit API contracts between modules. The payments module has no access to the KYC module's internal state. That's not convention — it's enforcement through the type system.
* *UIKit:* Biometrics, document verification SDKs, custom PIN entry UI — all of these need UIKit integration. In RIBs, UIKit is the native environment.

### Decision: RIBs

Not a single argument points toward MVVM here. Every criterion — cross-platform needs, navigation complexity, security, UIKit integration — leads to RIBs. The regulated industry and complex auth-gated navigation alone justify this choice.

An important point: even if one person is working on this project with an AI agent, RIBs here isn't about distributing work across a team. It's about the fact that the AI agent can generate each RIB module in isolation, with clear contracts at the boundaries. The more complex the project, the more the agent benefits from structural constraints — they prevent it from "getting lost" in the codebase.

### Takeaway

For fintech apps, RIBs isn't overengineering — it's a necessity. The entry cost (more boilerplate) pays for itself in safety and structural integrity that the AI agent maintains automatically.

***

## Case Study 3. Local Services Marketplace

### Context

An entrepreneur wants to build a marketplace for finding local service providers: plumbers, electricians, cleaners. Key screens: a feed of offerings, provider profiles, booking with date/time picker, in-app chat with the provider, Stripe payment, order history, user profile. They're working solo with an AI agent. Android is coming, but "not now." The business model anticipates growth.

### Applying the Decision Tree

**Step 1: Prototype or production?** — There's a business model with payments and growth plans — this is a production project.

**Additional signals:**

* *Android:* "Not now" — a classic signal that frequently turns into "needed yesterday" 6–8 months after launch.
* *Navigation:* Booking is a flow: select service → pick date → confirm → pay → result. There's an auth gate (unauthenticated users can browse but not book). Chat is a separate flow with real-time communication. This isn't trivial navigation.
* *Integrations:* Stripe SDK, chat (possibly WebSocket), push notifications, geolocation for finding nearby providers.

### Decision: RIBs

The project is clearly production, the navigation is non-trivial (booking flow, auth gates, chat), and the probability of Android is > 0. It might feel like RIBs is "too much" for a solo developer. But think about it differently: the AI agent handles all the boilerplate. The difference between "generate an MVVM screen" and "generate a RIB" is a few seconds for the agent. But the difference in structural support 6 months down the line is enormous.

With RIBs, the agent will add new features as isolated modules with clear boundaries. With MVVM, all the navigation and state gradually turns into a tangled mess that gets harder to unravel over time.

### Takeaway

When a project shows signs of growth (business model, non-trivial navigation, possible Android), it's better to lay down RIBs from the start. With an AI agent, the extra RIBs boilerplate is the agent's time, not yours. But the tech debt from the wrong architecture — that's your headache.

***

## Case Study 4. Corporate Directory

### Context

A company wants an internal app for employees: a contact directory, office map, meeting room booking, and a news feed. About 500 users. Budget is tight, they need to show results fast. Data comes from a corporate REST API. No Android planned — everyone has an iPhone.

### Applying the Decision Tree

**Step 1: Prototype or production?** — This is a tricky question. The app will be used in production, but it doesn't "grow" — its scope is fixed. It won't become a marketplace or a social network. It's essentially a utility for a specific set of tasks.

**Additional signals:**

* *Android:* Not planned.
* *Navigation:* Linear. Tab bar → list → detail. Booking is a simple form sheet. No branching flows.
* *Scaling:* Scope is fixed. Nobody expects the directory to grow to 50 screens.

### Decision: MVVM

Fixed scope, linear navigation, no Android plans. This is exactly the case where MVVM is the optimal choice. RIBs would add unnecessary structural complexity with zero benefit.

An important nuance: although the app will be used "in production," by its nature it's a utility with a bounded scope. The key question in the decision tree isn't "will it be in production?" — it's "will it grow?" A corporate directory with a clear spec doesn't grow.

If a year later someone says "let's add a vacation request workflow and expense tracking" — that's when you evaluate whether the scope has truly expanded enough to justify migration. But making that decision now, "just in case," is premature optimization.

### Takeaway

Not every "real" app needs a production architecture. If the scope is clear and bounded, MVVM delivers a better result in less time — even for corporate projects.

***

## Case Study 5. The Prototype That Took Off

### Context

Anna built a habit tracking app — a tracker where you check off daily habits and see statistics. Three screens: habit list, adding a new habit, stats dashboard. She chose MVVM — correctly, because it's a textbook prototype. The AI agent generated a working version in a few hours. She shipped it to the App Store and started gaining users.

Four months later she has 50,000 users. An investor wants in. New requirements appear: social features (challenges with friends), a subscription with a paywall, CloudKit sync, widgets, an Apple Watch companion, localization into 5 languages.

### Why This Is a Common Scenario

This is the classic "throwaway prototype that accidentally becomes the product" that the decision tree warns about. Anna is now facing a choice:

**Option A: Evolve the MVVM codebase.** Keep adding features on top of existing code. For complex flows (paywall, challenge onboarding), add lightweight flow coordinator objects — `@Observable` state machines that own navigation decisions for a single flow. This is NOT full MVVM+C: no coordinator protocol, no coordinator tree, no parent-child lifecycle. Just one concrete object per complex flow.

**Option B: Migrate to RIBs.** Rewrite the UI architecture from scratch. A growing product with non-trivial navigation — RIBs gives clear module boundaries and Android readiness in the future.

### Applying the Decision Tree

**Step 1: Prototype or production?** — It's unambiguously production now. 50,000 users, investment, paid subscriptions.

**Additional signals:**

* *Navigation:* Paywall with auth gate, challenge onboarding, friend invitation flow — navigation is getting complex.
* *Scope:* From 3 screens to 15+. The trend is clear — it will keep growing.
* *Widgets and Apple Watch:* These targets do NOT use RIBs — they run on pure SwiftUI. Migrating the main target to RIBs doesn't affect them at all.

### Recommendation

If you can set aside a few days for migration — **Option B (RIBs)**. Growing product, non-trivial navigation — everything points to RIBs. The migration will be a rewrite of the UI layer, but business logic (models, services, CloudKit code) transfers as-is because it lives in SPM modules, not in the architectural layer. With an AI agent, this isn't months of manual work — it's a focused sprint.

If there's absolutely no time for migration and the product is growing daily — **Option A** as a stopgap. Add flow coordinators for the paywall and onboarding. That buys a few months. But make a clear note to yourself: "RIBs migration is the next big step." Otherwise, tech debt accumulates to the point where migration becomes significantly harder.

### Takeaway

"The prototype that took off" is the most expensive architectural mistake if you're not prepared for it. Two rules that save you:

1. **At the start** — be honest that MVVM = throwaway. If there's even a 30% chance of growth, start with RIBs.
2. **When it takes off** — migrate proactively while the codebase is still manageable. With an AI agent, migration is days, not months. But the longer you wait, the harder it gets even for the agent.

***

## Summary

Choosing an architecture isn't about which one is "better." Both MVVM and RIBs are correct in their own context. The question is: what's your context?

| Your Situation                          | Recommendation                                                |
| --------------------------------------- | ------------------------------------------------------------- |
| Utility, fixed scope                    | **MVVM**                                                      |
| Prototype for idea validation           | **MVVM** (with a clear understanding of the rewrite boundary) |
| Production with growth potential        | **RIBs**                                                      |
| Android planned                         | **RIBs**                                                      |
| Complex navigation, auth gates, flows   | **RIBs**                                                      |
| Fintech, healthtech, regulated industry | **RIBs**                                                      |
| watchOS                                 | **MV** (always)                                               |

If you're in doubt — ask yourself one question: **"Am I ready to rewrite this code in a year?"** If yes — MVVM. If no — RIBs. If "I don't know" — probably RIBs.

***

*Based on the iOS App Architecture Decision Tree (2026). Modaal currently supports MVVM and RIBs, with plans for TCA and other patterns as demand warrants. Key assumptions that may shift: SwiftUI continues closing the gap with UIKit, the CombineRIBs community remains active, AI agent capabilities expand.*
