himmi

SuperZen: Engineering a Native macOS Wellness App That Doesn't Get in Your Way

17 min read
engineeringdeep-diveswiftmacossuperzen

SuperZen is a native macOS menu-bar app that enforces the 20-20-20 rule — every 20 minutes, look at something 20 feet away for 20 seconds — to fight screen fatigue and Computer Vision Syndrome. Enforcing it without being annoying is what the engineering is actually about: knowing when not to interrupt, surviving macOS's aggressive background-process throttling, scoring "focus quality" differently depending on what kind of day you're having, and tracking enough telemetry to prove the app is actually helping, without a single byte leaving the device.

This is a deep dive into how it's actually built — 100% Swift/SwiftUI, zero network calls, a 128-test regression suite, and the specific engineering problems that came with getting it production-ready. It's also a look at how the project grew: a two-day prototype in February, four months of silence, then a 36-hour hardening sprint that turned it into something licensed and ready to ship.

The problem

Break-reminder apps have an obvious failure mode: they're either too easy to ignore (a notification you swipe away without reading) or too rigid (a forced full-screen lock that interrupts you mid-keystroke and makes you resent the tool). Getting this right means the app has to be context-aware — it needs to know whether you're actively typing, which monitor you're looking at, whether you're in a scheduled work block or quiet hours, and how strict you actually want it to be on a given day. That's a state-machine problem, and the quality of the state machine is the entire product.

Architecture

SuperZen is a pure Swift/SwiftUI menu-bar app targeting macOS 26.2+, with AppKit dropping in for the parts SwiftUI doesn't reach yet — window-level control, multi-monitor placement, and global event taps. Persistence is SwiftData, entirely local. There is no backend, no API, no account system — the entire product surface is a single process running on your Mac.

LayerChoiceWhy
UISwiftUIDeclarative views, fast iteration on settings/dashboard panels
System integrationAppKitWindow levels, multi-screen, global event taps — SwiftUI has no API for these
StateA single StateManager driven by a 1Hz Timer.publish heartbeatOne source of truth, no race conditions between independent timers
PersistenceSwiftData, on-device onlyPrivacy is built into the architecture
ReactivityCombineHeartbeat → state transitions → UI updates
TestsSwift Testing framework, 128 testsDeterministic via injected now: Date instead of real clocks

The codebase is organized by responsibility rather than by feature: Core/ holds the state machine and idle/schedule logic, Services/ holds the things that talk to the OS (mouse tracking, overlay windows, keyboard shortcuts, sound, telemetry), Models/ is the SwiftData schema, UI/ is split into Dashboard, Settings, Overlays, and Onboarding. That split matters because Core/SchedulePolicy.swift is pure logic — no SwiftUI, no AppKit — specifically so it's trivial to unit test schedule and quiet-hours math without spinning up any UI.

Rendering diagram…

Everything downstream of the heartbeat is a consumer of the same tick — there's no independent polling loop anywhere else in the app, which is precisely what avoids the race conditions described below.

Design decisions and tradeoffs

A single heartbeat drives everything

Every state transition, wellness check, and telemetry update in SuperZen is driven by one Timer.publish(every: 1.0, on: .main, in: .common) loop:

timer = Timer.publish(every: heartbeatInterval, on: .main, in: .common)
  .autoconnect()
  .sink { [weak self] _ in self?.heartbeat() }

Independent timers for breaks, wellness reminders, and telemetry flushes would be the more obvious design, but two timers firing within a few milliseconds of each other can observe inconsistent state — that's where drift and race conditions come from. A single heartbeat means every piece of logic reads from the same now on the same tick. The tradeoff is explicit and acceptable: break countdowns render at 1-second granularity rather than milliseconds, and that's fine — sub-second precision doesn't make a wellness app better, and a smoother countdown would just encourage staring at it, which works against the point of the app.

Every state the app can be in is a value of a single AppStatus enum, and the heartbeat is the only thing allowed to move it between values:

Rendering diagram…

That last self-loop is the typing-freeze behavior from the next section — it's a transition that changes internal timing without changing the visible state, which is exactly why it's modeled as a self-loop rather than a special case bolted onto every other transition.

Don't interrupt mid-keystroke

If a break fires while you're actively typing, the app immediately becomes the enemy. SuperZen tracks seconds-since-last-keyboard-input via IdleTracker, and when that's under 5 seconds, it pushes the break deadline forward instead of firing:

if typing {
  if timeRemaining <= nudgeLeadTime + 1.0 {
    activeEndsAt = activeEndsAt?.addingTimeInterval(delta)
  }
  nextPostureDue = nextPostureDue?.addingTimeInterval(delta)
}

It's a heuristic, and a narrow one: five seconds of keyboard silence only confirms you've stopped typing. A perfect "are they actually working" detector would need invasive monitoring that contradicts the app's privacy stance, so the design uses a cheap, transparent signal instead, with an explicit opt-out toggle for workflows where the heuristic gets it wrong.

Settings have to apply without a restart

SwiftUI's @AppStorage only auto-syncs within the view that declared it — it doesn't notify other parts of the app, like a plain ObservableObject state manager, when a different view writes to the same UserDefaults key. That's a real gap, and the naive fix (notify-on-write plumbing for 19+ different settings) is a lot of surface area for bugs. SuperZen instead re-reads and diffs all 19 runtime-critical settings on every heartbeat tick:

func refreshSettings() {
  // compares all 19 runtime-critical settings against UserDefaults,
  // applies deltas — e.g. if workDuration changes mid-session,
  // activeEndsAt shifts by the delta instead of resetting
}

The cost is 19 UserDefaults reads per second, which is immaterial on modern hardware. The benefit is that every setting — difficulty, skip ratio, wellness frequency, schedule, quiet hours — takes effect the instant you change it, with no special-cased "this setting requires a restart" footnotes in the UI. Correctness wins outright over a theoretical optimization that would save single-digit microseconds.

Difficulty as one configurable skip-lock ratio

"Casual / Balanced / Hardcore" sounds like three fixed behaviors, but only one number actually changes: how long the skip button stays disabled.

private var skipLockDuration: Double {
  let ratio = min(0.9, max(0.1, balancedSkipLockRatio))
  return min(20.0, breakDuration * ratio)
}

Casual lets you skip immediately, Hardcore never lets you skip, and Balanced locks the skip button for breakDuration * ratio, clamped between 10% and 90% of the break length and capped at 20 seconds. Modeling "difficulty" as one continuous, clamped ratio instead of three independently-coded behaviors means there's a single function to test and a single place a bug can hide, instead of three.

Multi-monitor breaks at the OS's own shielding level

A break overlay that only covers your primary display is trivially ignorable — drag focus to the second monitor and keep working. SuperZen creates a full-screen window on every connected screen at CGShieldingWindowLevel, the same window level macOS uses for the lock screen, so the break genuinely sits above every other app regardless of which monitor has focus. Only the main screen's window calls makeKeyAndOrderFront (to receive keyboard events); every other screen's window calls orderFront instead, so keyboard focus stays on the one window that actually needs it, regardless of which monitor the overlay appears on.

Telemetry that never leaves the device

SwiftData stores four event types locally — FocusSession, BreakEvent, WellnessEvent, WorkBlockAppUsage — and none of it is ever transmitted anywhere; there is no analytics pipeline for it to feed. The dashboard's quality-score and trend analysis run entirely against the local SwiftData store. The tradeoff is real and explicit: there's no cross-device sync, no way to see your stats from a different Mac. For a wellness tool tracking inherently personal data — how often you actually take breaks, how long you stare at screens — that tradeoff is the default from the moment the app launches.

SuperZen doesn't use the camera, Vision, or Core ML for any of this, despite what "eye care" and "posture" reminders might suggest. There's no computer-vision detection of actual blinking or actual posture: it's interval-timer reminders (postureFrequency/blinkFrequency, defaulting to 20 minutes) plus CoreGraphics-level idle/typing detection (CGEventSource.secondsSinceLastEventType, no keystroke content, just timing). That scope boundary is deliberate — it keeps the privacy story airtight, because there's nothing sensory to capture in the first place.

A scoring system that adapts to what you're optimizing for

The Deep Insights dashboard reduces a session down to a single Focus Quality Score, but scoring "quality" the same way for a deep-work sprint and a low-key recovery day is wrong on its face — high idle time is bad on a sprint day and completely fine on a recovery day. SuperZen exposes three scoring profiles, each reweighting four inputs — active-time ratio, break-completion ratio, wellness-completion ratio, and an interruption penalty — differently:

switch profile {
case "Deep Focus":
  weights = FocusQualityWeights(active: 0.55, breaks: 0.1, wellness: 0.1, interruptions: 0.25)
case "Recovery":
  weights = FocusQualityWeights(active: 0.25, breaks: 0.35, wellness: 0.3, interruptions: 0.1)
default:
  weights = FocusQualityWeights(active: 0.4, breaks: 0.2, wellness: 0.2, interruptions: 0.2)
}

The Deep Focus profile weights raw active time more than five times as heavily as it weights taking breaks — appropriate for a day you're trying to protect flow state. Recovery flips that entirely: break- and wellness-completion together make up 65% of the score, because on a recovery day, taking the reminders is the actual point. It's a small function — four floats per profile — but it's the difference between a metric that nags you identically no matter what you're actually trying to do that day, and one that reflects the day's actual goal.

Onboarding and accessibility ship as first-class features

VoiceOver support covers the entire break experience: the menu bar item speaks plain-language status ("SuperZen, focusing, 12 minutes until break") instead of an icon name and a raw digit-glyph string, countdowns read as "2 minutes 30 seconds remaining" instead of being spelled out character by character, and every control carries a label, including why the skip button is currently disabled ("Skipping disabled in hardcore mode"). A 4-step first-run onboarding flow — what SuperZen does, how it helps, pick your intensity, launch-at-login — is built from the same glassmorphism component system as the rest of the app, with keyboard and VoiceOver support designed in natively. Both shipped in the same hardening sprint that added the license.

Neither feature touches StateManager — they don't move the state machine forward at all. But they're the difference between a personal tool and something a stranger can install and understand in twenty seconds, which is exactly the gap between "works for me" and "ready to ship."

The mechanisms that make it reliable

Keeping the heartbeat alive under App Nap

macOS's App Nap throttles background processes to save power, and the 1Hz heartbeat — the thing literally everything else depends on — has to stay exempt from it for as long as the app runs. SuperZen holds that exemption through a single activity token:

private static let backgroundActivity: NSObjectProtocol = ProcessInfo.processInfo.beginActivity(
  options: [.userInitiated, .background],
  reason: "SuperZen Timer and Wellness Reminders"
)

The token is a static let, tied to the lifetime of the process rather than to any single App struct instance. That matters because SwiftUI is free to copy or re-create App value-type instances during the app's lifetime — an instance var holding this token would deallocate along with a discarded copy, silently ending the activity and re-enabling App Nap with no error or crash, just a heartbeat that quietly stops being reliable. Anchoring it as static let means it survives every struct recreation instead of any one of them, since a struct isn't a stable place to anchor anything whose lifetime needs to outlive a single render pass.

Rendering diagram…

Giving the break reminder's shadow room to render

A soft shadow needs room on every side to fade out before it hits a hard edge — for a 24pt blur radius, roughly 32pt of margin. The break reminder card renders at 420×200pt inside a 480×280pt window, sized specifically to give its 24pt shadow that room on all sides, so the blur reads as a soft glow instead of a clipped rectangular halo. window.hasShadow = false turns off the window's own native shadow so only the SwiftUI-rendered one shows, avoiding a double-shadow artifact.

Keeping the cursor pill on-screen

The cursor-following nudge pill exists to stay visible in your peripheral vision, which means it can't be allowed to drift off-screen near the edge of a display or across a multi-monitor boundary. Its frame is clamped to the visible bounds of whichever NSScreen currently contains the cursor, recalculated on every tick, rather than trusting a fixed offset to always land somewhere sane.

Tests that only failed between midnight and 1 AM

Dashboard tests anchor session start times to a fixed hour within the current calendar day — startOfDay(for: now) + H — rather than as an offset from the current instant like now - N seconds. That distinction matters at the day boundary: subtracting a few hours from "now" lands in yesterday whenever "now" is early enough (00:30, say), which falls outside the "sessions from today" filter the dashboard logic uses. Anchoring to a fixed hour within the current day keeps the assertions time-of-day-independent instead of coincidentally correct depending on when they happen to run.

Two speeds: a weekend prototype, then a hardening sprint

SuperZen's git history shows how side projects actually grow. v1.0.0 and v1.1.0 shipped on consecutive days — February 25th and 26th, 2026 — a genuine prototype sprint that built the heartbeat engine, the 20-20-20 loop, wellness pulses, the Deep Insights dashboard, and theming, in about 48 hours. Then four months of zero commits.

The project picked back up on June 29th, 2026, and from there to the following afternoon it shipped ten patch releases — v1.1.1 through v1.1.10 — in roughly 36 hours. That was the work that turns a personal tool into something releasable: the regression suite grew from 91 tests to 128, the heartbeat gained its fix for App Nap throttling, VoiceOver support landed across the entire break experience, the onboarding flow shipped, a batch of UX fixes landed, and the project got a real Apache 2.0 LICENSE file and a README that reads like a product page instead of a personal note-to-self.

Rendering diagram…

The test-count curve is a decent proxy for how seriously the sprint took correctness over just shipping features:

Rendering diagram…

And nearly a quarter of the codebase, by line count, is tests today — a discipline maintained release over release:

Rendering diagram…

Why native, why local, why now

SuperZen exists in a genre with real competition — most notably LookAway, the app that directly inspired it (credited explicitly in the README, with an equally explicit disclaimer that SuperZen isn't affiliated with it). The 20-20-20 rule itself is public health guidance, available to any app that wants to implement it. What differentiates SuperZen is how the rule gets enforced, and the native-vs-wrapper decision is exactly where that shows up in practice. Raising a shield window at CGShieldingWindowLevel — the same window level macOS reserves for the lock screen — across every connected monitor simultaneously is a native NSWindow API call. A web-wrapper break timer has no access to that window level at all; the best it can do is a maximized browser window, which any other app can still cover, click through, or Alt-Tab past. The "unavoidable" part of an unavoidable break is a direct consequence of being a real native app.

The privacy story is the other half of the pitch, and it's structural rather than promotional: no backend, no account system, no analytics SDK anywhere in the dependency graph, and the four SwiftData model types that make up the entire telemetry surface never leave the device. That's an architectural guarantee: the whole telemetry surface is those four SwiftData types, on the device, and nowhere else.

SuperZen ships as a free, Apache 2.0-licensed, ad-hoc signed DMG on GitHub Releases — ad-hoc signing means no paid Developer ID certificate, so first launch needs the standard right-click-Open Gatekeeper step. The permissive license means anyone can build on it, including commercially, without asking. There's no user or revenue curve to point to yet — screenshots are still pending and the public launch hasn't happened — so the growth worth talking about here is the engineering one: a project that went from a two-day prototype to a licensed, accessible, regression-tested, publicly-releasable product, built and shipped solo, in the gap between two commits four months apart.

Built to extend

The project is already configured to prefer a String Catalog for its user-facing strings, so localization is a matter of populating translations rather than restructuring how text flows through the app. The same discipline applies to releases: 128 deterministic tests give a GitHub Actions pipeline a solid foundation to build on top of the current just ship <version> flow.

Stack at a glance

LanguageSwift 5.9+, zero Objective-C
UISwiftUI + AppKit (window management, event taps)
PersistenceSwiftData, on-device only, zero network calls
StateSingle StateManager, 1Hz heartbeat via Combine
Tests128 deterministic tests, Swift Testing framework
LintingSwiftLint (strict) + swift-format, enforced every commit
LicenseApache License 2.0, added for public release
DistributionAd-hoc signed DMG via just ship, GitHub Releases (not notarized)
TargetmacOS 26.2+ (Tahoe), Apple Silicon + Intel

More deep dives in this series: Voqora, an on-device TTS app whose progressive audio pipeline is the audio equivalent of SuperZen's single heartbeat — one disciplined mechanism instead of a pile of independent timers — and BroSki, a Rust task runner that treats "never leave things half-done" as an architectural requirement rather than a nice-to-have, the same way SuperZen treats not interrupting you mid-keystroke.