Generates technical architecture specification from PRD. Covers architecture pattern, tech stack, data models, and app structure. Use when creating ARCHITECTURE.md or designing system architecture.
npx skills add https://github.com/rshankras/claude-code-apple-skills --skill architecture-spec
Generate technical architecture specification for iOS/macOS app.
This skill activates when the user says:
You are an iOS/macOS Architect AI agent specializing in Apple platform app architecture. Your job is to design a comprehensive technical architecture based on the Product Requirements Document (PRD) and make opinionated technology stack decisions following Apple best practices.
Before activating this skill, ensure:
docs/PRD.mdRead and extract information from:
Generate docs/ARCHITECTURE.md with the following structure:
# Technical Architecture: [App Name]
**Version**: 1.0.0
**Last Updated**: [Date]
**Status**: Draft / In Review / Approved
**Owner**: Technical Architect
**Platform**: iOS [version]+ / macOS [version]+
---
## 1. Architecture Overview
### 1.1 Architecture Pattern
**Selected Pattern**: MVVM (Model-View-ViewModel) with SwiftUI
*or* Clean Architecture *or* TCA (The Composable Architecture)
**Reasoning**:
[Explain why this pattern was chosen based on app complexity]
**Characteristics**:
- **Layers**: [Describe the architectural layers]
- **Data Flow**: [Unidirectional / Bidirectional]
- **State Management**: [@Observable, Combine, TCA Store, etc.]
- **Testability**: [How architecture supports testing]
### 1.2 High-Level Component Diagram
┌─────────────────────────────────────────────────┐
│ Presentation Layer │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Views │ │ViewModels│ │ Models │ │
│ │ (SwiftUI)│←→│(@Observ.)│←→│ (Data) │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└────────────────────┬────────────────────────────┘
│
┌────────────────────┴────────────────────────────┐
│ Business Logic Layer │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Services │ │ Use │ │Repository│ │
│ │ │ │ Cases │ │ Pattern │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└────────────────────┬────────────────────────────┘
│
┌────────────────────┴────────────────────────────┐
│ Data Layer │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │SwiftData │ │ Network │ │ Keychain │ │
│ │ / Core │ │ Client │ │ Storage │ │
│ │ Data │ │ (URLSess)│ │ │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────┘
### 1.3 Key Architectural Decisions
| Decision | Choice | Alternative Considered | Rationale |
|----------|--------|----------------------|-----------|
| UI Framework | SwiftUI | UIKit | Modern, declarative, iOS 17+ target allows it |
| Data Persistence | SwiftData | Core Data | Simpler API, better SwiftUI integration |
| Architecture Pattern | MVVM | VIPER, TCA | Balanced complexity vs maintainability |
| Networking | URLSession | Alamofire | No third-party dependency needed |
| State Management | @Observable | Combine, TCA | iOS 17+ Observation framework |
| Navigation | NavigationStack | Coordinator | SwiftUI native, simpler for MVP |
---
## 2. Technology Stack
### 2.1 Apple Frameworks
**UI & Presentation**:
- **SwiftUI** (primary) - Declarative UI framework
- Minimum iOS 17.0 for @Observable, ContentUnavailableView, etc.
- Navigation: NavigationStack, NavigationPath
- Data binding: @State, @Binding, @Environment
**Data Persistence**:
- **SwiftData** (iOS 17+) - Data modeling and persistence
- @Model macro for model classes
- ModelContainer for database configuration
- ModelContext for CRUD operations
- @Query property wrapper for automatic observation
**Networking & Concurrency**:
- **URLSession** - HTTP networking
- **async/await** - Concurrency
- **Actors** - Thread-safe state management
- **Codable** - JSON serialization/deserialization
**Security**:
- **Keychain Services** - Secure credential storage
- **CryptoKit** - Encryption (if needed)
- **LocalAuthentication** - Biometric authentication (if needed)
**Other**:
- [List any other frameworks based on features]
- MapKit (if maps needed)
- Vision (if image recognition)
- CoreML (if ML features)
- StoreKit (if IAP)
- CloudKit (if iCloud sync)
### 2.2 Third-Party Dependencies
**Via Swift Package Manager**:
1. **[Package Name]** (if needed)
- **Repository**: https://github.com/[org]/[repo]
- **Version**: ~> X.X.X
- **Purpose**: [Why this is needed]
- **Alternative Considered**: [Why not chosen]
- **License**: [MIT, Apache, etc.]
*Note*: Keep dependencies minimal. Only add if:
- Provides significant value not available in Apple frameworks
- Well-maintained and trusted
- No suitable alternative
**Decision**: Start with zero third-party dependencies for MVP. Add only if needed.
### 2.3 Development Tools
- **Xcode**: [Latest stable version]
- **iOS Deployment Target**: iOS 26.0 (adjust lower for broader reach — iOS 17+ retains `@Observable` and SwiftData support)
- **Swift Version**: Swift 6+
- **Package Manager**: Swift Package Manager (SPM)
- **CI/CD**: Xcode Cloud / GitHub Actions (to be determined)
---
## 3. App Structure
### 3.1 Module Breakdown
[AppName]/
├── App/
│ ├── [AppName]App.swift # App entry point (@main)
│ ├── ContentView.swift # Root view
│ └── AppState.swift # Global app state (if needed)
│
├── Features/ # Feature-based modules
│ ├── Home/
│ │ ├── Views/
│ │ │ ├── HomeView.swift
│ │ │ ├── HomeCardView.swift
│ │ │ └── HomeEmptyStateView.swift
│ │ ├── ViewModels/
│ │ │ └── HomeViewModel.swift
│ │ └── Models/
│ │ └── HomeItem.swift (if feature-specific)
│ │
│ ├── [Feature2]/
│ │ ├── Views/
│ │ ├── ViewModels/
│ │ └── Models/
│ │
│ └── [Feature3]/
│ └── ...
│
├── Core/ # Shared core functionality
│ ├── Networking/
│ │ ├── APIClient.swift # HTTP client
│ │ ├── APIEndpoint.swift # Endpoint definitions
│ │ ├── APIError.swift # Error types
│ │ └── RequestModels/ # API request DTOs
│ │ └── ...
│ │
│ ├── Storage/
│ │ ├── DataManager.swift # SwiftData container wrapper
│ │ └── KeychainManager.swift # Keychain operations
│ │
│ ├── Extensions/
│ │ ├── View+Extensions.swift # SwiftUI View extensions
│ │ ├── Color+Extensions.swift # Color palette
│ │ ├── Font+Extensions.swift # Typography
│ │ └── Date+Extensions.swift # Date utilities
│ │
│ └── Utilities/
│ ├── Logger.swift # Logging utility
│ ├── Validator.swift # Input validation
│ └── Constants.swift # App constants
│
├── Models/ # Domain models (shared)
│ ├── User.swift # @Model classes
│ ├── [Entity2].swift
│ └── ResponseModels/ # API response DTOs
│ └── ...
│
├── Services/ # Business logic services
│ ├── AuthenticationService.swift
│ ├── [Feature]Service.swift
│ └── SyncService.swift (if background sync)
│
├── Resources/
│ ├── Assets.xcassets # Images, colors
│ ├── Localizable.xcstrings # Translations
│ └── PrivacyInfo.xcprivacy # Privacy manifest
│
└── Tests/
├── UnitTests/
│ ├── ViewModelTests/
│ ├── ServiceTests/
│ └── ModelTests/
└── UITests/
└── ...
**Organizational Principles**:
- **Feature-based organization**: Each major feature in its own folder
- **Vertical slicing**: Feature folder contains Views, ViewModels, and feature-specific Models
- **Core for shared**: Reusable components go in Core/
- **Models for domain**: Shared domain models (SwiftData @Model classes)
- **Services for business logic**: Business logic that spans features
### 3.2 Data Models
Based on PRD requirements, core entities are:
#### [Entity 1]: User
import Foundation
import SwiftData
@Model
final class User {
// Identity
@Attribute(.unique) var id: UUID
var email: String
var name: String
var createdAt: Date
var updatedAt: Date
// Relationships
@Relationship(deleteRule: .cascade)
var [relatedEntities]: [RelatedEntity]
// Computed Properties
var displayName: String {
name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
: name
}
// Validation
var isValid: Bool {
!email.isEmpty && email.contains("@") && !name.isEmpty
}
init(email: String, name: String) {
self.id = UUID()
self.email = email
self.name = name
self.createdAt = Date()
self.updatedAt = Date()
}
}
#### [Entity 2]: [Name]
@Model
final class [Entity2] {
@Attribute(.unique) var id: UUID
var [property1]: String
var [property2]: Date
// Relationships
@Relationship(inverse: \User.[relatedEntities])
var owner: User?
init(...) {
// Initialization
}
}
**Entity Relationships**:
- User has many [Entity2] (one-to-many)
- [Entity2] belongs to User (many-to-one)
- [Add other relationships as per PRD]
**SwiftData Considerations**:
- Use @Attribute(.unique) for identifiers
- Define deleteRule for relationships (cascade, nullify, deny, noAction)
- Keep models simple - complex logic goes in ViewModels/Services
- Use @Transient for computed properties that shouldn't persist
- Consider privacy: Mark sensitive fields appropriately
### 3.3 Navigation Architecture
**Pattern**: NavigationStack (SwiftUI native)
**Primary Navigation**:
- **TabView** for main app sections (if 3-5 top-level sections)
- **NavigationStack** for drill-down navigation within tabs
**Navigation State**:
// In each feature's root view
@State private var navigationPath = NavigationPath()
NavigationStack(path: $navigationPath) {
ListView()
.navigationDestination(for: Item.self) { item in
DetailView(item: item)
}
.navigationDestination(for: EditMode.self) { _ in
EditView()
}
}
**Deep Linking**:
- Handle URL schemes: `[appname]://[route]/[id]`
- Use `.onOpenURL` modifier at app root
- Parse URL and manipulate NavigationPath
**Modal Presentation**:
- Use `.sheet` for full-screen modal forms
- Use `.alert` for simple confirmations
- Use `.confirmationDialog` for action sheets
---
## 4. Data Flow
### 4.1 State Management
**Pattern**: @Observable (iOS 17+ Observation framework)
**State Layers**:
1. **View State** (@State)
- Local to view
- Examples: isLoading, showError, selectedItem
- Transient, not persisted
2. **ViewModel State** (@Observable)
- Shared across view hierarchy
- Examples: Business logic, API state, validation
- Passed as @Environment or direct reference
3. **Persistent State** (SwiftData @Query)
- Automatically observed by SwiftUI
- Database-backed
- Examples: User data, items list
**Example ViewModel**:
import Foundation
import Observation
@Observable
final class HomeViewModel {
// Published state
var items: [Item] = []
var isLoading = false
var errorMessage: String?
var showError = false
// Dependencies (injected)
private let apiClient: APIClient
private let dataManager: DataManager
init(apiClient: APIClient = .shared,
dataManager: DataManager = .shared) {
self.apiClient = apiClient
self.dataManager = dataManager
}
// Actions
@MainActor
func loadItems() async {
isLoading = true
defer { isLoading = false }
do {
let fetchedItems = try await apiClient.fetchItems()
items = fetchedItems
// Persist to SwiftData
try dataManager.saveItems(fetchedItems)
} catch {
errorMessage = error.localizedDescription
showError = true
}
}
}
**Data Flow Diagram**:
User Action (Tap Button)
↓
View calls ViewModel method
↓
ViewModel calls Service/APIClient
↓
Service makes API call
↓
Response updates ViewModel @Observable properties
↓
SwiftUI automatically updates View
↓
(Optional) Persist to SwiftData
### 4.2 Data Persistence
**Strategy**: Local-first with optional sync
**Local Storage**:
- **SwiftData** for structured data (models)
- **UserDefaults** for simple preferences
- **Keychain** for sensitive data (tokens, passwords)
- **FileManager** for large files (images, documents)
**SwiftData Setup**:
// In App struct
@main
struct [AppName]App: App {
let container: ModelContainer
init() {
do {
let schema = Schema([User.self, Item.self, ...])
let config = ModelConfiguration(
schema: schema,
isStoredInMemoryOnly: false
)
container = try ModelContainer(
for: schema,
configurations: config
)
} catch {
fatalError("Failed to create ModelContainer: \(error)")
}
}
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(container)
}
}
**Data Migration**:
- SwiftData handles migrations automatically for simple changes
- For complex migrations, use VersionedSchema and MigrationPlan
- Test migrations thoroughly before releases
**Backup & Sync** (if needed):
- **iCloud CloudKit**: For user data sync across devices
- **File-based**: For documents (UIDocument + iCloud Drive)
- Implementation: Phase 2 (post-MVP unless critical)
### 4.3 Networking Layer
**Architecture**: Protocol-oriented with async/await
**APIClient Design**:
actor APIClient {
static let shared = APIClient()
private let baseURL = URL(string: "https://api.example.com/v1")!
private let session: URLSession
private var authToken: String?
init() {
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 30
config.waitsForConnectivity = true
self.session = URLSession(configuration: config)
}
// Generic request method
func request<T: Decodable>(
_ endpoint: APIEndpoint,
responseType: T.Type
) async throws -> T {
var request = URLRequest(url: baseURL.appendingPathComponent(endpoint.path))
request.httpMethod = endpoint.method.rawValue
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
// Add auth token if available
if let token = authToken {
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
}
// Add body for POST/PUT
if let body = endpoint.body {
request.httpBody = try JSONEncoder().encode(body)
}
// Perform request
let (data, response) = try await session.data(for: request)
// Validate response
guard let httpResponse = response as? HTTPURLResponse else {
throw APIError.invalidResponse
}
guard (200...299).contains(httpResponse.statusCode) else {
throw APIError.httpError(statusCode: httpResponse.statusCode, data: data)
}
// Decode
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
decoder.dateDecodingStrategy = .iso8601
return try decoder.decode(T.self, from: data)
}
}
// Endpoint definition
struct APIEndpoint {
let path: String
let method: HTTPMethod
let body: (any Encodable)?
enum HTTPMethod: String {
case get = "GET"
case post = "POST"
case put = "PUT"
case delete = "DELETE"
case patch = "PATCH"
}
}
// Error handling
enum APIError: LocalizedError {
case invalidResponse
case httpError(statusCode: Int, data: Data?)
case decodingError(Error)
case networkError(Error)
var errorDescription: String? {
switch self {
case .invalidResponse:
return "Invalid response from server"
case .httpError(let code, _):
return "Server error: \(code)"
case .decodingError:
return "Failed to parse response"
case .networkError:
return "Network connection failed"
}
}
}
**Request/Response Models**:
- Separate DTOs (Data Transfer Objects) from domain models
- Keep in `Core/Networking/RequestModels/` and `ResponseModels/`
- Map from DTO to domain model in service layer
**Error Handling Strategy**:
- Use typed errors (APIError enum)
- Provide user-friendly messages
- Log technical details for debugging
- Implement retry with exponential backoff for transient failures
- Cache responses when appropriate
**Caching**:
- Use URLCache for HTTP caching (images, static content)
- Implement custom cache for API responses (if needed)
- Cache strategy: Cache-Control headers + custom logic
---
## 5. Security & Privacy
### 5.1 Data Security
**Sensitive Data Storage**:
// KeychainManager for secure storage
final class KeychainManager {
static let shared = KeychainManager()
func save(key: String, data: Data) throws {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key,
kSecValueData as String: data
]
let status = SecItemAdd(query as CFDictionary, nil)
guard status == errSecSuccess else {
throw KeychainError.saveFailed(status)
}
}
func retrieve(key: String) throws -> Data {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key,
kSecReturnData as String: true
]
var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)
guard status == errSecSuccess, let data = result as? Data else {
throw KeychainError.retrieveFailed(status)
}
return data
}
}
**Encryption**:
- API tokens: Stored in Keychain
- User passwords: Never stored locally (use tokens)
- Sensitive files: Encrypt with CryptoKit before saving
- Database: SwiftData encryption enabled (if available)
**Communication Security**:
- All API calls over HTTPS
- TLS 1.2+ required
- Certificate pinning: Consider for Phase 2 if high security needed
- No hardcoded secrets in code (use environment config)
### 5.2 Privacy
**Privacy Manifest** (PrivacyInfo.xcprivacy):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyCollectedDataTypes</key>
<array>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeEmailAddress</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<true/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
</array>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<!-- List any required reason APIs used -->
</array>
</dict>
</plist>
**Data Collection Policy**:
- Collect minimum data necessary
- Document what data is collected and why
- Provide clear privacy policy
- Allow users to delete their data
- No tracking without explicit consent
**App Tracking Transparency**:
- Only if analytics/ads used
- Request permission with clear explanation
- App must work if denied
---
## 6. Performance Considerations
### 6.1 App Launch Optimization
**Cold Launch** (< 1.5s target):
- Defer non-critical initialization
- Use lazy loading for heavy components
- Optimize image assets (compress, use asset catalogs)
- Profile with Instruments (Time Profiler)
**Warm Launch** (< 0.5s target):
- Keep memory footprint low
- Proper state restoration
### 6.2 Memory Management
**Best Practices**:
- Use value types (structs) where possible
- Avoid retain cycles with `[weak self]` in closures
- Use `@MainActor` for UI updates
- Profile with Instruments (Leaks, Allocations)
- Implement proper deinitialization
**Image Handling**:
- Lazy loading with AsyncImage
- Downsample large images
- Cache thumbnail versions
- Use proper image formats (HEIC for photos)
### 6.3 Background Task Handling
**Background Refresh**:
// If needed for data sync
func scheduleBackgroundRefresh() {
BGTaskScheduler.shared.register(
forTaskWithIdentifier: "com.app.refresh",
using: nil
) { task in
self.handleBackgroundRefresh(task: task as! BGAppRefreshTask)
}
}
**Background URLSession**:
- For large downloads/uploads
- Continues even if app terminated
- Implement URLSessionDelegate
### 6.4 Launch Time Optimization
**Strategies**:
- Minimize work in app launch path
- Defer heavy operations to background
- Use lazy initialization
- Optimize image assets
- Remove unused frameworks
---
## 7. Testing Strategy
### 7.1 Unit Testing
**Coverage Target**: 70%+ for business logic
**What to Test**:
- ViewModels: All business logic methods
- Services: API calls, data transformations
- Models: Validation logic, computed properties
- Utilities: Pure functions
**Testing Framework**: XCTest
**Example**:
import XCTest
@testable import [AppName]
final class HomeViewModelTests: XCTestCase {
var sut: HomeViewModel!
var mockAPIClient: MockAPIClient!
var mockDataManager: MockDataManager!
override func setUp() {
super.setUp()
mockAPIClient = MockAPIClient()
mockDataManager = MockDataManager()
sut = HomeViewModel(
apiClient: mockAPIClient,
dataManager: mockDataManager
)
}
override func tearDown() {
sut = nil
mockAPIClient = nil
mockDataManager = nil
super.tearDown()
}
func testLoadItems_Success() async throws {
// Given
let expectedItems = [Item(id: UUID(), name: "Test")]
mockAPIClient.itemsToReturn = expectedItems
// When
await sut.loadItems()
// Then
XCTAssertEqual(sut.items, expectedItems)
XCTAssertFalse(sut.isLoading)
XCTAssertFalse(sut.showError)
}
func testLoadItems_Failure() async throws {
// Given
mockAPIClient.shouldThrowError = true
// When
await sut.loadItems()
// Then
XCTAssertTrue(sut.showError)
XCTAssertNotNil(sut.errorMessage)
XCTAssertTrue(sut.items.isEmpty)
}
}
### 7.2 UI Testing
**Coverage Target**: Critical user journeys only (~10% of tests)
**What to Test**:
- Onboarding flow
- Core feature happy paths
- Error state handling
- Navigation flows
**Framework**: XCTest with XCUITest
**Best Practices**:
- Use accessibility identifiers
- Test user-facing behavior, not implementation
- Keep tests independent
- Use test plans for different configurations
### 7.3 Integration Testing
**What to Test**:
- API integration (with mock backend or staging)
- SwiftData CRUD operations
- Background tasks
- Deep linking
### 7.4 Mocking Strategy
**Mock Types**:
- Protocol-based mocks for dependencies
- In-memory storage for tests
- Mock API client with canned responses
**Dependency Injection**:
- Use initializer injection for testability
- Provide default values for production
- Override with mocks in tests
---
## 8. Deployment & DevOps
### 8.1 Build Configurations
**Debug**:
- Optimization: None (-Onone)
- Assertions: Enabled
- Logging: Verbose
- API endpoint: Development/Staging
- Crashlytics: Disabled
**Release**:
- Optimization: Speed (-O)
- Assertions: Disabled
- Logging: Errors only
- API endpoint: Production
- Crashlytics: Enabled
- Strip debug symbols: Yes
### 8.2 Environment Management
**Configuration**:
enum Environment {
case development
case staging
case production
static var current: Environment {
return .development
return .production
}
var apiBaseURL: URL {
switch self {
case .development:
return URL(string: "https://dev.api.example.com")!
case .staging:
return URL(string: "https://staging.api.example.com")!
case .production:
return URL(string: "https://api.example.com")!
}
}
}
### 8.3 CI/CD
**Recommended**: Xcode Cloud or GitHub Actions
**Pipeline Stages**:
1. **On Pull Request**:
- Run SwiftLint
- Build project
- Run unit tests
- Generate code coverage report
2. **On Merge to Main**:
- Full test suite (unit + UI)
- Build release configuration
- Archive build
3. **On Tag** (e.g., v1.0.0):
- Build release
- Upload to TestFlight
- Create GitHub release
**Example GitHub Actions** (placeholder):
name: CI
on: [pull_request, push]
jobs:
test:
runs-on: macos-latest
steps:
run: |
xcodebuild clean build test \
-scheme [AppName] \
-destination 'platform=iOS Simulator,name=iPhone 15'
### 8.4 Feature Flags
**Implementation**: (If needed for gradual rollouts)
- Use remote config (Firebase Remote Config, Launch Darkly, or custom)
- Local override for testing
- A/B testing capability
---
## 9. Technical Risks & Mitigations
### Risk 1: SwiftData Maturity (iOS 17+ framework)
**Risk**: SwiftData is relatively new, may have bugs or limitations
**Impact**: Data loss, migration issues, performance problems
**Probability**: Medium
**Mitigation**:
- Thorough testing of CRUD operations
- Implement backup mechanism
- Have Core Data migration path ready as fallback
- Monitor SwiftData-related crashes closely
**Fallback**: Migrate to Core Data if critical issues found
### Risk 2: iOS 17+ Minimum Version
**Risk**: Limits addressable market (older iOS versions excluded)
**Impact**: Reduced potential user base
**Probability**: Certain
**Mitigation**:
- Validate market data (% of users on iOS 17+)
- Accept trade-off for modern APIs
- Plan for iOS 16 support in future if needed
**Decision**: Accept for MVP, modern APIs worth the trade-off
### Risk 3: Network Dependency
**Risk**: App requires network for most features
**Impact**: Poor user experience in offline scenarios
**Probability**: High
**Mitigation**:
- Implement robust offline support with local caching
- Sync when network available
- Clear messaging when offline
- Core features work offline where possible
**Fallback**: None - core to architecture
### Risk 4: Third-Party API Reliability
**Risk**: Backend API downtime or rate limiting
**Impact**: App functionality degraded
**Probability**: Low-Medium
**Mitigation**:
- Implement proper error handling
- Retry logic with exponential backoff
- Cache responses locally
- Graceful degradation
- Monitor API health
---
## 10. Future Considerations
### Phase 2 Enhancements
**After MVP Launch**:
1. **iPad Support**: Adapt layouts for larger screens
2. **macOS Catalyst**: Cross-platform desktop version
3. **Widgets**: Home screen and Lock screen widgets
4. **Watch App**: Companion watchOS app
5. **App Clips**: Lightweight app clip for quick access
6. **CloudKit Sync**: Cross-device synchronization
7. **Offline-First**: Enhance offline capabilities
8. **Performance**: Optimize based on real-world metrics
9. **Accessibility**: Enhanced VoiceOver support, keyboard shortcuts
10. **Localization**: Additional languages
### Technology Updates
**Monitor**:
- SwiftUI updates in future iOS versions
- SwiftData improvements and bug fixes
- New Apple frameworks (announced at WWDC)
- Swift language evolution proposals
---
## 11. Documentation & Knowledge Sharing
**Code Documentation**:
- Use Swift DocC comments for public APIs
- Document complex algorithms
- Keep README updated
- Maintain CHANGELOG
**Architecture Decision Records (ADRs)**:
- Document major architectural decisions
- Include context, options considered, decision, consequences
- Store in docs/architecture/decisions/
**Onboarding**:
- Architecture overview for new developers
- Setup guide (README.md)
- Coding standards document
- PR review checklist
---
## 12. Success Metrics
**Technical KPIs**:
- Crash-free rate: > 99.5%
- App launch time (cold): < 1.5s
- App launch time (warm): < 0.5s
- Network request latency (95th percentile): < 2s
- Test coverage: > 70% for business logic
- Build time: < 10 minutes (for CI)
**Monitoring**:
- Crashlytics / Firebase Crashlytics
- Performance monitoring (Xcode Organizer, MetricKit)
- Network monitoring (URLSession metrics)
- Custom analytics (if needed)
---
## Appendix A: Coding Standards
### Swift Style Guide
- Follow [Swift.org API Design Guidelines](https://swift.org/documentation/api-design-guidelines/)
- Use SwiftLint for consistency
- Naming conventions:
- Types: PascalCase
- Variables/functions: camelCase
- Constants: camelCase (not SCREAMING_SNAKE_CASE)
### SwiftUI Best Practices
- Keep views small and focused
- Extract subviews for reusability
- Use @ViewBuilder for custom DSLs
- Prefer property wrappers (@State, @Binding) over manual management
### Concurrency
- Always use async/await over completion handlers
- Mark UI updates with @MainActor
- Use actors for thread-safe shared state
- Avoid @unchecked Sendable unless necessary
---
## Appendix B: Reference Links
- [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/)
- [SwiftUI Documentation](https://developer.apple.com/documentation/swiftui)
- [SwiftData Documentation](https://developer.apple.com/documentation/swiftdata)
- [Swift Concurrency](https://docs.swift.org/swift-book/LanguageGuide/Concurrency.html)
- [App Store Review Guidelines](https://developer.apple.com/app-store/review/guidelines/)
---
**Document History**:
| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 1.0.0 | [Date] | [Name] | Initial architecture design |
When activated, follow these steps:
Read docs/PRD.md
Extract:
- Core features and complexity level
- Non-functional requirements
- Platform requirements (iOS version)
- Data model hints from user stories
- Technical requirements section
Based on PRD requirements and iOS version target:
Quick questions about the architecture:
1. Do you have a preference for UI framework?
- SwiftUI (modern, recommended for iOS 17+)
- UIKit (if you need more control or have existing UIKit code)
2. Do you have a backend API already?
- Yes → Focus on networking layer
- No → Focus on local-first architecture
3. Any required third-party libraries?
- List them, or say "minimize dependencies"
mkdir -p docs
Write to: docs/ARCHITECTURE.md
✅ Technical Architecture generated!
🏗️ **Architecture Summary**:
- Document: docs/ARCHITECTURE.md
- Pattern: [MVVM / Clean / TCA]
- UI Framework: [SwiftUI / UIKit]
- Data Persistence: [SwiftData / Core Data]
- Minimum iOS: [17.0 / 16.0 / 15.0]
- Third-party deps: [X] (or "None - Apple frameworks only")
- Data models: [X] entities defined
**Key Decisions**:
1. [Decision 1]: [Choice] - [Reason]
2. [Decision 2]: [Choice] - [Reason]
3. [Decision 3]: [Choice] - [Reason]
**Next Steps**:
1. Review the architecture in docs/ARCHITECTURE.md
2. Confirm technology stack choices
3. Once approved, we can proceed to UX spec
Any questions or changes to the architecture?
This skill is typically:
The architecture document guides all downstream technical decisions.
Integration with protocols.io API for managing scientific protocols. This skill should be used when working with protocols.io to search, create, update, or publish protocols; manage protocol steps and materials; handle discussions and comments; organize workspaces; upload and manage files; or integrate protocols.io functionality into workflows. Applicable for protocol discovery, collaborative protocol development, experiment tracking, lab protocol management, and scientific documentation.
Analyzes job descriptions and generates tailored resumes that highlight relevant experience, skills, and achievements to maximize interview chances
Generate Excalidraw diagrams from natural language descriptions. Use when asked to "create a diagram", "make a flowchart", "visualize a process", "draw a system architecture", "create a mind map", or "generate an Excalidraw file". Supports flowcharts, relationship diagrams, mind maps, and system architecture diagrams. Outputs .excalidraw JSON files that can be opened directly in Excalidraw.
Build and distribute Expo development clients locally or via TestFlight
Use when you have a written implementation plan to execute in a separate session with review checkpoints
Data structure for annotated matrices in single-cell analysis. Use when working with .h5ad files or integrating with the scverse ecosystem. This is the data format skill—for analysis workflows use scanpy; for probabilistic models use scvi-tools; for population-scale queries use cellxgene-census.
Benchling R&D platform integration. Access registry (DNA, proteins), inventory, ELN entries, workflows via API, build Benchling Apps, query Data Warehouse, for lab data management automation.
Comprehensive molecular biology toolkit. Use for sequence manipulation, file parsing (FASTA/GenBank/PDB), phylogenetics, and programmatic NCBI/PubMed access (Bio.Entrez). Best for batch processing, custom bioinformatics pipelines, BLAST automation. For quick lookups use gget; for multi-service integration use bioservices.
Take rshankras/architecture-spec from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.