CycleWingman 1.0: a weather app for relationships
cyclewingmanreleaseengineering
Our first consumer app is live on the App Store. CycleWingman is a "relationship weather" app: you enter your partner's cycle info (with their knowledge and comfort — the app makes you confirm it), and it gives you a simple daily forecast — Green, Yellow, Orange or Red — with an energy, mood and intimacy outlook and one concrete "do this / avoid this" tip. Not a period tracker for her; a heads-up system for you.
The product idea
Cycle apps are almost universally built for the person with the cycle. The partner — the person who could actually use a heads-up before planning a big night out or starting a difficult conversation — gets nothing. CycleWingman flips the audience: one glance in the morning, and you know how to show up today. The weather metaphor keeps it honest and light: forecasts are probabilistic, people are not their hormones, and a red day is a "bring snacks" day, not an excuse.
The engineering story
An app with no servers. None.
The core promise is "Data Not Collected" — the App Privacy label, literally. No accounts, no cloud, no analytics, no crash reporting. Cycle data lives in local storage on the phone and syncs to the watch over Apple's device-to-device channel. Even the Wingman+ subscription runs through StoreKit 2 entirely on-device: Apple signs the transactions, the app verifies entitlements locally, and there is no receipt server. The privacy page can say "we couldn't read your data even if we wanted to" because there is nowhere for that data to arrive.
One forecast engine, two languages, provable parity
The UI is a web app (Next.js, statically exported) inside a thin native shell — which means the forecast engine is TypeScript. But the Apple Watch app is native SwiftUI, and shipping a WebView to a watch is not a thing. So the engine exists twice: the TS original and a Swift port in a package called WingmanCore.
Two implementations of the same domain logic is a classic drift factory, so the TS side exports golden fixtures — hundreds of (input, expected-forecast) pairs regenerated on demand — and the Swift package's test suite replays them. If the ports ever disagree by a single day-color, CI fails. Parity isn't a code-review promise; it's a failing test.
A native feel on a web foundation
The shell isn't just a WebView wrapper: the tab bar is a real native UITabBar, the status bar and background chrome are managed from Swift, and the web layer talks to the shell over a tiny message bridge (StoreKit, WatchConnectivity, appearance). On iPad the app deliberately renders as a centered phone-width card — a small-screen product shouldn't pretend to be a spreadsheet.
Honesty as a design constraint
The app is rated 17+, repeats "not medical advice, not contraception" in the UI, the store listing and the terms, and requires explicit confirmation that your partner knows and is comfortable. These aren't legal fig leaves; they shaped the product. Forecast copy says "likely" and "typical patterns", the disclaimer ends with "she's the source of truth", and there are no fertility-planning features at all — deliberately.
What's in 1.0
- Today's forecast: status color, cycle phase, energy / mood / intimacy outlook, a one-liner, and a do/avoid tip.
- 5-day outlook, and a full monthly calendar with Wingman+.
- Up to three partners with Wingman+, each with an independent forecast — including pill-pack schedules, not just natural cycles.
- An Apple Watch app with per-partner status and outlook.
- iPhone, iPad and Apple Watch. Private by design.
