Skip to content
Anirudh Rao
← All work

SwiftUI learning app on Firebase

Mystic Academy.

An iOS learning app where courses, units, and lessons live in nested Firestore collections and stream into SwiftUI views live, with Firebase Auth, onboarding, and a financial-literacy starter catalog.

Mystic Academy is a SwiftUI learning app backed by Firebase. Learners browse courses by category, pick a learning track, and work through units of lessons that unlock as they go. The starter content leaned into financial literacy, with tracks like Credit 101, Taxes 101, and Banking 101.

The problem

Course apps live or die on how their content is structured. Courses contain units, units contain lessons, and each lesson has its own state. The goal was an iOS app where that hierarchy lives in the backend, so new courses appear without shipping an app update, and the interface stays live as content changes.

Architecture

Content is modeled as nested Firestore subcollections: Courses/{course}/Units/{unit}/Lessons. Views bind to those collections with @FirestoreQuery, so the UI updates live when the data does. Course and instructor images load from Firebase Storage, and categories carry their own SF Symbol icon and design-system color.

How it works

Queries that follow the hierarchy

A course screen doesn't know its data path until it knows which course it's showing, so each view points its query at the right subcollection when it appears. The course view loads that course's units in order and looks up the instructor's profile; each unit then does the same for its lessons.

swift · 5 lines
.onAppear {
    $users.predicates.append(.isEqualTo("uid", "\(course.instructor)"))
    $units.path = "Courses/\(course.uid)/Units"
    $units.predicates.append(.orderBy("desc", true))
}

Session handling

A SessionStore observable object wraps Firebase Auth. It listens for auth state changes and publishes whether the user is signed in, and it's injected into the view tree as an environment object so any screen can react to sign-in and sign-out without passing state down by hand.

Course detail

Course pages show the instructor, rating, enrollment, difficulty, language, and required tools, with pricing that handles free courses and discounts. Lessons render with lock and completion states so learners can see where they are in a unit at a glance.

What I'd change next

  • Move progress to per-user records. Lock and completion flags live on the shared lesson documents, so one learner finishing a lesson would mark it complete for everyone; a Users/{uid}/progress collection fixes that.
  • Rank popular courses from Firestore. The home screen sorts the bundled sample courses by enrollment rather than the live query results.
  • Surface auth errors. Sign-up and sign-in calls don't handle failures, so a wrong password fails silently instead of telling the user.
esc
↑↓ to move · ↵ to selectk=16