Skip to content

Reward-E Architecture

Reward-E is an iOS app for families to track star rewards for kids. Parents award stars (each worth a configurable amount, e.g., 10 NOK) that kids can save or spend.

Tech Stack

Component Technology
Frontend SwiftUI (iOS 17+)
Backend Firebase (Auth + Firestore)
Feedback CutiELink SDK
Build System XcodeGen

Architecture Pattern

MVVM with a Service Layer and centralized app state:

flowchart TB
    subgraph app["Reward-E iOS App"]
        views["SwiftUI Views"]
        appstate["AppState<br/>(ObservableObject)"]
        services["Services"]
        models["Models<br/>(Codable)"]
    end

    subgraph firebase["Firebase"]
        auth["Firebase Auth<br/>(Apple Sign-In)"]
        firestore["Cloud Firestore<br/>(Real-time sync)"]
    end

    views --> appstate
    appstate --> services
    services --> models
    services --> auth
    services --> firestore
Layer Implementation Responsibility
Views SwiftUI Views UI rendering, user input
State AppState (@ObservableObject) Central app state, coordinates services
Services AuthService, FamilyService, GoalService Business logic, Firebase operations
Models User, Family, Child, Transaction Data structures (Codable)

Project Structure

ios/
├── RewardE/
│   ├── RewardEApp.swift          # App entry point, Firebase init
│   ├── ContentView.swift         # Root view (onboarding vs main)
│   ├── Models/
│   │   ├── AppState.swift        # Main app state
│   │   └── Models.swift          # User, Family, Child, Transaction
│   ├── Services/
│   │   ├── AuthService.swift     # Apple Sign-In + Firebase Auth
│   │   ├── FamilyService.swift   # Firestore CRUD
│   │   ├── GoalService.swift     # Savings goal management
│   │   └── ConnectionService.swift
│   └── Views/
│       ├── Components/           # Reusable UI components
│       └── ...
├── RewardE.xcodeproj
└── project.yml                   # XcodeGen config

Key Decisions

Decision Rationale
Firebase over iCloud Real-time sync via Firestore listeners is simpler. Family sharing via invite codes is easier.
Parent-only MVP Simplifies auth flow. Kids view stars on parent's device.
Configurable star value Different families want different values (default 10 NOK).
Firestore transactions for spending Prevents race conditions where two simultaneous spend requests could exceed balance.
GoalService extracted from AppState Single Responsibility -- AppState was handling too many concerns.

Firestore Data Model

flowchart TB
    subgraph firestore["Cloud Firestore"]
        families["families/{familyId}"]
        children["families/{familyId}/children/{childId}"]
        transactions["families/{familyId}/transactions/{txId}"]
        users["users/{userId}"]
    end

    families --> children
    families --> transactions
    users --> families
  • families -- Family settings (star value, currency, invite code)
  • children -- Child profiles (name, avatar, star balance)
  • transactions -- Star awards and spending history
  • users -- User profiles linked to families

Firebase Configuration

Property Value
Project ID reward-e-app
Region europe-west1
Bundle ID no.invotek.RewardE
Auth Apple Sign-In
Persistence Enabled by default (offline-first)

Firestore security rules are auto-deployed via GitHub Actions when firestore.rules is modified.