Convert a React App to iOS

5-minute tutorial

This walkthrough takes a Next.js e-commerce app and converts it to a native SwiftUI iOS app using Morphkit. Every command shown is real output from the tool.

Prerequisites

Step 1: Plan the Conversion

Start with morphkit plan to see what Morphkit will build. This is always free — no API key needed.

Terminal
npx morphkit-cli plan ./my-nextjs-shop
# iOS Conversion Plan: ShopKit ## Detected Stack No special backend integrations detected — using standard URLSession. ## Summary | Total screens analyzed | 4 | | Screens included | 3 | | Screens excluded | 1 | ## Recommended Screens - Products (list) [MEDIUM] — list layout maps well to mobile - Cart (list) — list layout maps well to mobile - ProductsDetail (detail) — detail layout maps well to mobile ## Excluded Screens - Home — marketing page, not needed on mobile

Morphkit analyzed 13 TypeScript files, found 4 routes, 8 components, 7 state patterns, and 3 API endpoints. It recommends 3 screens for mobile and excludes the marketing homepage.

If your app uses Supabase, Stripe, or SSE streaming, Morphkit auto-detects them here and generates the right iOS SDK integrations automatically.

Step 2: Generate the iOS Project

Terminal
npx morphkit-cli generate ./my-nextjs-shop -o ./ios-app -n ShopKit
Generated Project Summary App name: ShopKit Output: ./ios-app/ShopKit Total files: 38 High confidence: 32 Medium confidence: 4 Generated 38 files in 743ms

Morphkit generated a complete Xcode project with:

DirectoryContents
Models/Codable structs from your TypeScript interfaces (Product, CartItem, Cart)
Views/SwiftUI views for each screen (ProductsView, CartView, ProductsDetailView)
Navigation/TabView + NavigationStack with typed routes
Networking/URLSession API client with async/await, retry logic, TLS 1.2+
State/@Observable stores mapped from your Zustand/Redux state
Theme/Color+Theme.swift from your Tailwind config colors

What a generated view looks like

Here's the ProductsView.swift that Morphkit generated from your app/products/page.tsx:

// Generated by Morphkit from: app/products/page.tsx

import SwiftUI

struct ProductsView: View {
    @State private var products: [Product] = []
    @State private var searchQuery: String = ""
    @State private var isLoading: Bool = false
    @State private var errorMessage: String?

    var body: some View {
        List {
            ForEach(products) { (product: Product) in
                NavigationLink(value: AppRoute.productsDetail(id: String(describing: product.id))) {
                    HStack(spacing: 12) {
                        AsyncImage(url: URL(string: product.imageUrl)) { image in
                            image.resizable().aspectRatio(contentMode: .fill)
                        } placeholder: {
                            Image(systemName: "photo.circle.fill")
                                .foregroundStyle(.secondary)
                        }
                        .frame(width: 44, height: 44)
                        .clipShape(RoundedRectangle(cornerRadius: 8))

                        VStack(alignment: .leading) {
                            Text(product.name)
                                .font(.headline)
                            Text(product.price, format: .currency(code: "USD"))
                                .font(.subheadline)
                                .fontWeight(.semibold)
                        }
                    }
                }
            }
        }
        .searchable(text: $searchQuery)
        .refreshable { await loadData() }
        .navigationTitle("Products")
        .task { await loadData() }
    }

    private func loadData() async {
        isLoading = true
        defer { isLoading = false }
        do {
            products = try await APIClient.shared.fetchProducts()
        } catch {
            errorMessage = error.localizedDescription
        }
    }
}

Notice: proper SwiftUI idioms (NavigationStack, @State, .task, async/await), product images via AsyncImage, search, pull-to-refresh, and type-safe navigation.

Step 3: Build and Verify

Terminal
cd ios-app && swift build
Build complete! (10.77s)

Zero errors. Morphkit guarantees the generated project compiles on first build.

Terminal
npx morphkit-cli verify ./ios-app
Build Status: PASS (0 errors) Screen Completion: 4/4 (100%) API Wiring: 12/12 (100%) Model Completeness: 3/3 (100%) Overall: 100% complete

For simple apps, Morphkit generates everything — 100% complete. For complex apps (like a SaaS with Supabase + Stripe), you'll see MORPHKIT-TODO markers that the AI completion step resolves.

Step 4: Complete with AI (Optional)

If your project has remaining TODOs, run morphkit complete to have Claude resolve them automatically:

Terminal
ANTHROPIC_API_KEY=sk-ant-... npx morphkit-cli complete ./ios-app --verbose
Morphkit Complete TODOs found: 9 Completing ProductsView (3/12 screens, 7 TODOs remaining) Resolved 2 TODOs (5 remaining in file) ... TODOs resolved: 9 TODOs remaining: 0 Build status: pass

The AI reads each view file, the APIClient, and the model structs, then writes the implementation. It validates syntax with swiftc before writing and stops after 3 consecutive non-progress iterations.

Step 5: Open in Xcode

Terminal
open ios-app/Package.swift

Select an iOS Simulator (iPhone 16 Pro recommended), hit Run, and see your app.

Bonus: Apps with Supabase

If your web app uses Supabase for auth and database, Morphkit auto-detects it and generates SupabaseManager.swift:

// Generated by Morphkit — Supabase Swift SDK integration
import Supabase

@Observable
final class SupabaseManager {
    static let shared = SupabaseManager()
    let client: SupabaseClient

    func signIn(email: String, password: String) async throws { ... }
    func fetch<T: Decodable>(_ table: String, type: T.Type) async throws -> [T] { ... }
    func insert<T: Encodable>(_ table: String, value: T) async throws { ... }
}

// Views call SupabaseManager directly:
products = try await SupabaseManager.shared.fetch("products", type: Product.self)

The generated Package.swift automatically includes the Supabase Swift SDK as a dependency. Just add your Supabase URL and anon key to SupabaseManager.swift and you're connected.

Bonus: Using with Claude Code

Register Morphkit's MCP server for the ultimate AI-powered workflow:

Terminal
npx morphkit-cli setup

Then in Claude Code, just ask: "Convert my web app at ./my-saas to iOS"

Claude Code will call morphkit_plan, morphkit_generate, and then use morphkit_complete_screen to wire up every screen automatically.


Ready to try it?

Get Started Free

20 conversions/month free. No credit card required.