Skip to content

DOC

Créer une app iOS native depuis une API avec Happy et Steve

Orchestration d'une API complète (Happy) vers une app iOS/macOS/watchOS production-ready (Steve)

Créer une app iOS native depuis une API avec Happy et Steve

Contexte

Vous avez un produit web et vous voulez offrir une première-classe expérience native sur iOS, macOS, watchOS, tvOS et visionOS. Ce workflow orchestre deux agents : Happy conçoit l’API exhaustive complète (REST ou GraphQL) adaptée à tous les clients, puis Steve la consomme pour construire un starter kit SwiftUI compilable, des tests Swift, et accompagne jusqu’au déploiement App Store Connect.

Prérequis

Phase 1 (Happy — API Design)

  • Projet web existant (Next.js, Rails, Django, etc.)
  • Stack backend connu et documenté
  • Modèles de données et endpoints existants (ou spécification préliminaire)
  • Optionnel : OpenAPI 3.1 spec si API existe déjà

Phase 2 (Steve — iOS Implementation)

  • Xcode 16+ avec Swift 6
  • iOS deployment target: 16.0+
  • macOS deployment target: 13.0+ (optionnel)
  • watchOS deployment target: 10.0+ (optionnel)
  • Developer certificate + App Store Connect access

Ecosystem Prerequisites

  • Happy génère docs/api/ (source de vérité)
  • Steve lit docs/api/ pour construire natives
  • Fluke (Android) réutilisera la même docs/api/ sans redéfinir

Étapes

1. Phase 1 : Conception API avec Happy

Invoquer Happy pour auditer le projet et concevoir l’API :

/ulk:happy
# ou
happy
# ou
API design
# ou
concevoir API

2. Happy Phase 0-1 : Diagnostic et cadrage

Happy pose des questions :

🏗️ Happy — Architecte API
━━━━━━━━━━━━━━━━━━━━━━━━

Diagnostic du projet web:
  Framework     : Next.js 15
  Backend       : Node.js/Express (optionnel, détecté)
  Base de données: PostgreSQL (Neon)
  Auth          : JWT + OAuth2

Clients prévus:
  ✅ Web (React)
  ✅ iOS (SwiftUI)
  ✅ Android (Flutter/Kotlin)
  ☐ CLI
  ☐ Partenaires tiers

Style API:
  ✅ REST (recommandé pour mobile)
  ☐ GraphQL (complexe pour mobile)

Cadrage:
1. Versioning? (URI: /v1/ vs Header: Accept)
2. Auth? (JWT Bearer, API Key, OAuth2)
3. Rate limiting? (Oui, recommandé)
4. Offline sync? (Oui, pour mobile)
5. Push notifications? (APNs + FCM)

3. Happy Phase 2-4 : Audit et conception API

Happy génère docs/api/ :

docs/api/
├── README.md                          # Overview + quick start
├── openapi.yaml                       # Spec complète (OpenAPI 3.1)
├── auth.md                            # Auth flows (JWT, OAuth2, etc.)
├── endpoints/
│   ├── users.md                       # GET /users, POST /users, etc.
│   ├── posts.md
│   ├── comments.md
│   └── ...
├── schemas/
│   ├── User.json
│   ├── Post.json
│   └── ...
├── push.md                            # APNs + FCM setup
├── sync.md                            # Offline sync strategy
└── errors.md                          # Error codes + handling

Exemple docs/api/endpoints/users.md :

## GET /users

Fetch paginated list of users.

### Query Parameters
- `page` (number, default: 1)
- `limit` (number, default: 20, max: 100)
- `search` (string, optional): Search by name/email

### Response

Status: 200 OK

\`\`\`json
{
  "data": [
    {
      "id": "user-123",
      "name": "John Doe",
      "email": "john@example.com",
      "avatar": "https://...",
      "createdAt": "2026-04-14T10:30:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 150
  }
}
\`\`\`

### POST /users

Create a new user.

### Request Body

\`\`\`json
{
  "name": "Jane Doe",
  "email": "jane@example.com",
  "password": "secure_password"
}
\`\`\`

### Response

Status: 201 Created

4. Phase 2 : Implémentation iOS avec Steve

Une fois docs/api/ généré par Happy, invoquer Steve :

/ulk:steve
# ou
steve
# ou
SwiftUI
# ou
iOS app

5. Steve Phase 0-1 : Diagnostic et setup

Steve lit docs/api/ et configure le projet :

🍎 Steve — Orchestrateur Apple
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Lisant docs/api/...
  ✅ OpenAPI 3.1 trouvé
  ✅ 12 endpoints détectés
  ✅ Auth: JWT Bearer
  ✅ Push: APNs + FCM supporté

Platforms cibles:
  ✅ iOS 16.0+
  ✅ macOS 13.0+
  ✅ watchOS 10.0+
  ☐ tvOS (optionnel)
  ☐ visionOS (optionnel)

Dépendances Swift:
  ✅ URLSession (built-in)
  ✅ SwiftData (built-in, iOS 17+)
  ✅ async/await (Swift 5.5+)
  + Packages: Alamofire, Apollo (GraphQL opt.), Combine

Configuration App Store Connect:
  1. App ID created
  2. Certificates configured
  3. Provisioning profiles ready

6. Steve Phase 2-5 : Génération starter kit

Steve génère un projet Xcode compilable :

MyApp/
├── MyApp.swift                        # @main app entry
├── Models/
│   ├── User.swift                     # Decodable structures
│   ├── Post.swift
│   └── ...
├── Services/
│   ├── APIClient.swift                # Gère requêtes API
│   ├── AuthService.swift              # JWT + OAuth2
│   ├── PushNotificationService.swift
│   └── OfflineSyncService.swift
├── ViewModels/
│   ├── UserListViewModel.swift
│   ├── PostDetailViewModel.swift
│   └── ...
├── Views/
│   ├── ContentView.swift              # Root navigation
│   ├── UserListView.swift
│   ├── PostDetailView.swift
│   ├── AuthView.swift
│   └── SettingsView.swift
├── Tests/
│   ├── APIClientTests.swift
│   ├── UserListViewModelTests.swift
│   └── ...
└── MyApp.xcodeproj                    # Xcode project (compilable)

Exemple de sortie

APIClient.swift (généré) :

import Foundation

class APIClient {
  static let shared = APIClient()
  private let baseURL = URL(string: "https://api.example.com")!
  private var token: String?

  func request<T: Decodable>(
    _ endpoint: String,
    method: String = "GET",
    body: Encodable? = nil
  ) async throws -> T {
    var request = URLRequest(url: baseURL.appendingPathComponent(endpoint))
    request.httpMethod = method
    
    if let token = token {
      request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
    }
    
    if let body = body {
      request.httpBody = try JSONEncoder().encode(body)
      request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    }
    
    let (data, response) = try await URLSession.shared.data(for: request)
    
    guard let httpResponse = response as? HTTPURLResponse,
          (200...299).contains(httpResponse.statusCode) else {
      throw APIError.requestFailed
    }
    
    return try JSONDecoder().decode(T.self, from: data)
  }
  
  func setAuthToken(_ token: String) {
    self.token = token
  }
}

enum APIError: Error {
  case requestFailed
  case decodingFailed
  case unauthorized
}

Variantes

  • Variante A : GraphQL au lieu de REST — Happy peut concevoir une API GraphQL, Steve l’implémente avec Apollo iOS
  • Variante B : Offline-first sync — Happy conçoit sync strategy (optimistic updates, conflict resolution), Steve l’implémente avec SwiftData
  • Variante C : Multiple platforms — Steve crée starter kits parallèles pour iOS + macOS + watchOS + tvOS depuis la même docs/api/

Agents enchaînés

Flux orchestré (Happy → Steve) :

Happy (mobile/49) — Conception API
  ├─ Phase 0 : Diagnostic projet web (5 min)
  ├─ Phase 1 : Cadrage clients (5 min)
  ├─ Phase 2 : Audit endpoints existants (20 min)
  ├─ Phase 3 : Conception complète (20 min)
  └─ Output : docs/api/ (OpenAPI 3.1)

Steve (mobile/27) — Implémentation iOS
  ├─ Phase 0 : Lire docs/api/ (5 min)
  ├─ Phase 1 : Setup Xcode + App Store Connect (10 min)
  ├─ Phase 2 : Générer Models + Services (30 min)
  ├─ Phase 3 : Générer Views + ViewModels (30 min)
  ├─ Phase 4 : Générer Tests (20 min)
  └─ Output : Xcode project compilable + deploy instructions

Après déploiement iOS, Fluke (48) réutilise la même docs/api/ pour Android.

Troubleshooting

SymptômeCause probableRésolution
”Happy can’t detect endpoints”Projet web trop complexe ou mal documentéFournir OpenAPI spec ou relancer avec --manual
”Steve reports missing App Store Certificate”Developer account non configuréLancer asc auth login et créer certificat via App Store Connect
”Models decoding fails”JSON schema doesn’t match API responseVérifier endpoints réels et relancer Steve avec --skip-models pour édition manuelle
”Push notifications not working”APNs key not configuredGénérer APNs key dans App Store Connect, configurer dans Steve via --apns-key

Voir aussi

  • ./12-web-to-flutter.md — Créer une app Android/Flutter (même API, autre platform)
  • ./02-blackemperor-pre-release.md — Pre-release orchestrator (inclut iOS deployment)
  • agents/mobile/49-happy.md — Documentation Happy (API design)
  • agents/mobile/27-steve.md — Documentation Steve (iOS implementation)
  • agents/_shared/mobile-protocol.md — Protocole mobile complet
  • App Store Connect : https://appstoreconnect.apple.com — Developer dashboard