SPED Goals — IEP & Goal Tracking App for Special Education Teachers

This product was built to help special-education teachers spend less time on admin work and more time on student intervention.
From a business lens, the project drives value in four ways:
- Improves teacher retention and daily engagement by reducing friction in logging student progress.
- Increases instructional quality by surfacing at-risk students earlier (risk scoring, reminder workflows, due-date warnings, and summary views).
- Expands monetization opportunities with a production-ready subscription and commerce stack (RevenueCat + Shopify + order history).
- Reduces rollout risk through feature flags, staged environments, and strong test coverage around high-risk flows (notifications, store, auth).
Product + Technical Stack
- Platform: iOS 16+ app in Swift.
- UI layer: UIKit-first architecture (ViewControllers, Storyboards, programmatic navigation), plus SwiftUI for WidgetKit extension.
- Data/backend: Firebase Auth, Firestore, Remote Config, Analytics, Cloud Messaging.
- Server logic: Firebase Cloud Functions (Node.js 20) for webhook/event processing (subscription and commerce sync paths).
- Commerce: Shopify Storefront GraphQL client for native catalog/cart flows, with WebView fallback for resilience.
- Subscriptions: RevenueCat integration for entitlement management.
- Supporting libraries: CocoaPods (
SwiftyJSON,Charts) + SPM dependencies (Firebase SDKs, Google Sign-In, RevenueCat, IQKeyboardManager). - CI/dev tooling: local scripts for notification test suites, typography guard checks, and release version bumping.
Technical constraints
Because this is a native iOS product, rendering is client-side native rendering, not web SSR/CSR.
The rendering approach is intentionally hybrid:
- Main app: UIKit renders screens immediately and hydrates with Firestore/network data asynchronously.
- Navigation shell: root scene decides logged-in vs onboarding flow at runtime, then tab composition is rebuilt based on Remote Config feature flags.
- Store experience: runtime switch between native Shopify catalog screens and WebView fallback to keep the business flow live even if native store prerequisites are disabled.
- Widget: SwiftUI WidgetKit timeline rendering reads precomputed student snapshots from shared storage; app-side services periodically refresh and write ranked students for fast widget draw time.
Key Challenges and How They Were Solved
1) Reliable reminders across real-world device behavior
Challenge:
Local reminders can drift or duplicate due to timezone changes, DST transitions, app lifecycle events, and evolving student targets.
Solution:
- Built deterministic reminder identifiers (
reminder.<student>.<progress>.<timestamp>) and reconciliation logic. - Rescheduled on app active and significant time/timezone changes.
- Applied capped scheduling windows to stay inside iOS pending-notification limits.
Business outcome:
Teachers get predictable reminders, improving consistency of progress logging without operational overhead.
2) Preventing notification data inconsistency
Challenge:
Notification inbox data can become inconsistent when local notifications, remote delivery, and Firestore mirrors update concurrently.
Solution:
- Added idempotent mirror sync patterns with serialized sync execution.
- Used transactional read-state updates and chunked bulk mark-as-read writes.
- Backed this with dedicated notification hardening tests and index/rules support.
Business outcome:
Inbox reliability improves trust and lowers support burden caused by duplicate/stale notifications.
3) Safe monetization rollout (subscription + commerce)
Challenge:
Introducing payments and commerce in an existing education app can break UX and create identity/ownership mismatches.
Solution:
- Implemented RevenueCat entitlement setup with guarded initialization.
- Added Shopify native store with feature-gated rollout and WebView fallback.
- Built guest-to-auth order claim flow so purchases remain attached to the right account after login.
Business outcome:
Monetization can scale without sacrificing user trust or causing checkout-related drop-off.
4) Balancing speed with accessibility and maintainability
Challenge:
Legacy-style UIKit codebases often drift into inconsistent typography/accessibility behavior over time.
Solution:
- Standardized typography tokens with Dynamic Type support across UIKit + SwiftUI surfaces.
- Added a guard script to block non-compliant hard-coded font usage in UI code.
Business outcome:
Lower accessibility risk, more consistent UI quality, and reduced long-term maintenance cost.
5) Performance under data-heavy teacher workflows
Challenge:
Teachers may manage many students and targets; slow list loads hurt daily usage.
Solution:
- Parallelized student/progress fetch flows.
- Added short-lived cache strategy for read-heavy screens.
- Precomputed ranked widget snapshots during fetch to avoid expensive widget-time computation.
Business outcome:
Faster perceived app responsiveness and improved day-to-day usability.