iOS Quick Start
This guide will help you build your first iOS application with Cuppa and SwiftUI.
Creating Your First View
Create a new SwiftUI view in ios/App/Views/HomeView.swift:
import SwiftUI
import CuppaUI
struct HomeView: View {
@StateObject private var viewModel = HomeViewModel()
var body: some View {
VStack(spacing: 20) {
Text("Welcome to Cuppa!")
.font(.largeTitle)
.bold()
CuppaButton(
title: "Get Started",
style: .primary,
action: {
viewModel.handleGetStarted()
}
)
if viewModel.isLoading {
ProgressView()
}
}
.padding()
}
}
Creating a ViewModel
Create the corresponding ViewModel using shared Cuppa logic:
import Foundation
import Combine
import CuppaCore
class HomeViewModel: ObservableObject {
@Published var isLoading = false
@Published var items: [Item] = []
func handleGetStarted() {
isLoading = true
Task {
do {
// Use shared Cuppa data fetching
let data = try await CuppaData.fetch("api/items")
await MainActor.run {
self.items = data
self.isLoading = false
}
} catch {
print("Error: \\(error)")
await MainActor.run {
self.isLoading = false
}
}
}
}
}
Adding Navigation
Set up navigation in ContentView.swift:
import SwiftUI
import CuppaRouter
struct ContentView: View {
var body: some View {
CuppaNavigationStack {
HomeView()
.cuppaRoute("/")
ProfileView()
.cuppaRoute("/profile")
SettingsView()
.cuppaRoute("/settings")
}
}
}
Using Cuppa Components
Cuppa provides pre-built SwiftUI components:
Buttons
// Primary button
CuppaButton(title: "Submit", style: .primary) {
handleSubmit()
}
// Secondary button
CuppaButton(title: "Cancel", style: .secondary) {
handleCancel()
}
// Outlined button
CuppaButton(title: "Learn More", style: .outlined) {
openDocs()
}
Form Inputs
struct LoginView: View {
@State private var email = ""
@State private var password = ""
var body: some View {
VStack(spacing: 16) {
CuppaTextField(
text: $email,
placeholder: "Email",
keyboardType: .emailAddress
)
CuppaSecureField(
text: $password,
placeholder: "Password"
)
CuppaButton(title: "Sign In", style: .primary) {
handleSignIn()
}
}
.padding()
}
}
Lists
struct ItemListView: View {
let items: [Item]
var body: some View {
CuppaList(items) { item in
HStack {
Text(item.title)
.font(.headline)
Spacer()
Image(systemName: "chevron.right")
.foregroundColor(.gray)
}
}
}
}
Integrating with Shared Code
Use your shared TypeScript/JavaScript business logic from iOS:
import CuppaBridge
class DataManager {
static func fetchUserData() async throws -> User {
// Call shared TypeScript function
let result = try await CuppaBridge.call(
function: "getUserData",
args: []
)
return try JSONDecoder().decode(User.self, from: result)
}
}
Adding Plugins
Integrate Cuppa plugins for common functionality:
Authentication Plugin
import CuppaAuth
// Sign in with email
await CuppaAuth.signIn(
email: email,
password: password
)
// Sign out
await CuppaAuth.signOut()
// Get current user
let user = CuppaAuth.currentUser
Data Plugin
import CuppaData
// Query data
let items = try await CuppaData.query("items", filters: [
"category": "featured"
])
// Mutate data
try await CuppaData.mutate("items/create", data: newItem)
Running Your App
Build and run your app:
# Run on iOS simulator
pnpm ios
# Run on specific device
pnpm ios --device="iPhone 15 Pro"
Next Steps
- Learn about iOS Architecture to understand how Cuppa works
- Explore the SwiftUI Components library
- Browse the full Components Reference