Inspiration

Outnudge began with a simple question: how can an activity app help someone get outside on an ordinary day without turning every outing into a performance test?

I wanted to combine the clarity of a small daily quest with a calm, supportive experience. Instead of rewarding maximum mileage, Outnudge focuses on consistency, variety, and recovery. A ten-minute walk should count just as meaningfully as a long hike or bike ride.

What it does

Outnudge is an iPhone companion for walking, hiking, running, and biking.

It creates an achievable daily quest based on the user’s goals, preferred activity, recent outings, routine, and reflections. If the plan feels too ambitious, it can become a gentler ten-minute start.

Users can:

  • Record routes, distance, duration, pace, and elevation with GPS
  • Explore curated outdoor ideas with MapKit context
  • Build streaks, earn XP, and follow weekly progress
  • Set gentle reminders and reflect after an outing
  • Save completed workouts to Apple Health with permission
  • Share achievement cards without exposing their route or location

Activities and reflections are stored locally, and no Outnudge account is required.

Outnudge Plus is optional. It adds Apple Weather context and deeper activity statistics, while GPS recording and the core habit experience remain free.

How I built it

Outnudge is a native SwiftUI app built for iPhone.

Core Location powers GPS recording and elevation samples, while MapKit displays recorded routes, resolves nearby places, and supports curated outing ideas. Location samples are filtered for accuracy, age, and realistic movement speeds.

Active recordings are saved to protected checkpoints during an outing. If the app is interrupted or relaunched, Outnudge restores only confirmed distance, time, elevation, and route points. The session returns paused until the user chooses to continue, so the app never invents activity data for missing time.

SwiftData stores activities, GPS points, progress, and Apple Health sync state. I also built a one-time migration from an earlier local JSON archive, preserving existing activities and retaining the original archive as a rollback copy.

Apple Health sync is optional and retry-aware. Outnudge saves its local activity first and attaches the activity’s UUID to the HealthKit workout. This lets the app find a previously completed save during a retry instead of creating a duplicate workout.

RevenueCat manages current offerings, localized prices, trial eligibility, purchases, restores, and the ios_pro entitlement. The checkout is a custom SwiftUI experience, while RevenueCatUI provides Customer Center for active members. Missing offerings, offline refreshes, and unavailable purchase configuration all have explicit states, and free recording remains available.

The public website was built with Next.js, React, and TypeScript and deployed through Laravel Cloud.

Challenges I ran into

Reliable outdoor recording was the biggest engineering challenge. GPS can be noisy, the app can move into the background, and the process can be interrupted entirely. I addressed this with filtered samples, atomic checkpoints, careful save ordering, and a paused recovery state that never guesses missing progress.

App Review uncovered a SwiftData launch crash caused by an ownership mistake. The repository retained its ModelContext, but the factory-created ModelContainer had already been released before the first fetch. I changed the repository to own both for their full lifetime, unified simulator and device persistence, and added regression coverage for startup, relaunch, migration, and GPS and HealthKit field round trips.

HealthKit presented another subtle case: a workout save could succeed immediately before the app persisted its HealthKit identifier. Adding an external activity UUID and durable sync states made retries substantially safer and prevented duplicate workouts.

Subscription presentation was another important lesson. After App Review feedback, I redesigned the purchase area so the complete localized price and billing period are the most prominent information. Trial details appear only for eligible customers and remain secondary to the amount they will actually be billed.

Accomplishments that I’m proud of

I’m proud that Outnudge grew from a SwiftUI prototype into an app available on the App Store with real GPS recording, interruption recovery, local persistence, optional Apple Health sync, adaptive quests, reminders, reflections, Apple Weather, and a production RevenueCat purchase flow.

I’m especially proud that the implementation supports the product’s values: no account is required, personal activity history stays local, shared cards omit location data, and purchasing infrastructure never blocks the free recording experience.

What I learned

I learned that reliability is part of product design. A friendly interface matters, but trust comes from recovering an interrupted outing accurately, preventing duplicate workouts, preserving data during migrations, and explaining failure states honestly.

I also learned that subscription design involves much more than connecting an SDK. Entitlements, localized store data, eligibility, restore behavior, accessibility, offline states, and clear billing disclosure must all work together.

Finally, designing a gentle habit loop requires restraint. Smaller starts and recovery need to count, while rewards must avoid pushing people toward unhealthy intensity.

What’s next

Next, I want to broaden outing discovery and add GPX import and export, verified route geometry, and offline map packages.

After more physical-device background and battery testing, Apple Watch and Live Activities are the next platform steps. I also plan to keep refining the reward system so it encourages healthy consistency without adding pressure.

Built With

Share this project:

Updates

Submission history