DEV Community

garry
garry

Posted on

Building a Breathing App — Why Simplicity Was the Hardest Part

The Trap of Feature Creep

When I started building Lunair, my breathing exercise app for iOS, I had a Notion board full of ideas. Guided meditations, social sharing, streaks, gamification, AI-powered breathing recommendations. The works.

Six weeks in, I had a bloated prototype that did everything poorly and nothing well. The core experience — helping someone breathe — was buried under menus and onboarding flows.

Stripping It Down

The turning point was watching someone use the app for the first time. They opened it, stared at the home screen for ten seconds, then asked "where do I start?" That was the moment I realized I had failed at the one thing that mattered.

I spent the next two weeks removing features. It was painful. Every feature I cut represented hours of work. But each removal made the app feel lighter, more focused.

// Before: A sprawling navigation structure
TabView {
    HomeView()
    ExploreView()
    StatsView()
    ProfileView()
    SettingsView()
}

// After: One screen, one purpose
BreathingView(pattern: selectedPattern)
Enter fullscreen mode Exit fullscreen mode

What "Simple" Actually Means in Code

Simple UI does not mean simple code. In fact, the opposite is usually true. When you strip away navigation chrome, every pixel has to earn its place. The breathing animation needed to feel organic, not mechanical. The timing had to be precise enough to guide but forgiving enough to not stress someone out.

I spent more time on the easing curve of a single circle animation than I did on entire view controllers in previous projects:

struct BreathingCircle: View {
    @State private var scale: CGFloat = 0.6

    var body: some View {
        Circle()
            .fill(breathingGradient)
            .scaleEffect(scale)
            .animation(
                .easeInOut(duration: inhaleDuration),
                value: scale
            )
    }
}
Enter fullscreen mode Exit fullscreen mode

The Paradox of Minimal Design

Here is what nobody tells you about minimal apps: users notice every flaw. In a complex app, a slightly off animation or an awkward transition gets lost in the noise. In a minimal app, it is the entire experience.

I rewrote the main breathing view four times. Not because it was broken, but because "good enough" felt jarring in a context where there was nothing else to look at.

Lessons Learned

  1. Start with the core interaction, not the feature list. If your app's primary action does not feel great in isolation, no amount of features will save it.
  2. Simplicity is a continuous practice. Every update, I fight the urge to add "just one more thing."
  3. Measure by what you remove. The best sessions I had building Lunair were the ones where the line count went down.

Building a simple app taught me more about software craft than any complex project I have shipped. The constraint forced better decisions at every level — architecture, design, and user experience.

If you are building something in the health or wellness space, resist the urge to compete on features. Compete on feel.

Top comments (0)