Inspiration
Couples who live together often can't say the one thing that matters most tonight: "How about today?" Asking risks a no; a no hurts; so nobody asks. The problem is not desire, it is the cost of bringing it up. Tacit removes that cost by putting a machine in between: each person answers privately, and only when both say yes does anything happen.
What it does
Tacit is a Home Screen widget for two people. Two dots sit side by side — the left one is you, the right one is your partner.
- Press twice to send. The first press only arms the dot; if you don't press again within ten seconds it quietly goes back. A mistaken tap never leaves your phone.
- One bit reaches your partner. Nothing else — no message, no time, no count.
- Both on = a quiet match notification. One on = nothing. Silence is a no, and no one has to say it.
- Nothing is kept. No history, calendar, streaks, statistics, read receipts or online status. Everything clears when the date changes.
- It reads as nothing from across the room. The widget shows no words (only "Set up" before pairing). Notifications are deliberately vague.
- No accounts. No email, no password, no server of ours. Everything stays inside the couple's own iCloud.
- Pairing is physical. The only way to pair is to hold both phones together and scan a QR code. There is no way to find or reach a stranger.
- Free, with a Tip Jar. Every feature is free. An optional Tip Jar (three consumable tips) lives inside the app. Paying changes nothing — and the app says so.
How we built it
- Swift / SwiftUI, iOS 17+. The app itself is setup-only; the product is the widget.
- WidgetKit interactive widgets + App Intents for the two-tap arming flow, with the arming state shared through an App Group container so the widget and the app agree.
- CloudKit only. A shared record zone per couple, one
Signalrecord plus a handful ofPingrecords that exist solely to drive silent push notifications. No custom backend, no third-party analytics. - RevenueCat powers the Tip Jar. It is isolated in its own Swift package target (
TacitTip) so the SDK never links into the widget extension. We call it with an anonymous ID only, neverlogIn(), and no signal data is ever passed to it — RevenueCat sees Apple's receipt and nothing else. This let us keep App Privacy honest: the only disclosed data type is Purchase History. - XcodeGen + fastlane + a local
ascCLI for a fully scripted release path, with the human kept in the loop only at the four gates (requirements, plan, verification, release). - Built almost entirely by an AI engineering team (Claude Code sessions) coordinated through GitHub Issues, with a human approving each gate.
Challenges we ran into
- A widget that must never lie. WidgetKit cannot promise timely redraws, and a widget extension can read but not reliably write shared state. We designed the arming flow so that every stale-state case fails closed (shows off) rather than open, and verified the partner's state right before confirming a match so neither phone shows a false "Both of you, today".
- Privacy as a hard constraint, not a setting. Vague notification copy, no text on the widget, no server — each of these removed a whole class of features we would otherwise have shipped.
- Shipping the first IAP. A consumable's first submission must ride along with a new app version, so the Tip Jar could only go live with 1.0.2, after 1.0 and 1.0.1 were already in the store.
- Keeping a large AI-built codebase honest. We ended up writing our own lint rules (comment hygiene, citation drift, forbidden shortcuts, pipe-safe test helpers) because "the test says green" turned out to be the most dangerous sentence in the project.
Accomplishments that we're proud of
- Shipped 1.0 on August 16, 2026, two updates since, and a working RevenueCat purchase flow — during the Shipaton window.
- An app that stays useful with zero stored data and zero accounts.
- A release pipeline where a single command archives, uploads, stages metadata in two languages and validates readiness.
What we learned
- Restraint is a feature. Every time we asked "what should we add?" the better answer was "what can we refuse to know?"
- A monetization layer can be added without touching the privacy story, if it is isolated by construction.
- Machine-checked rules beat written rules: the moment a guideline became a lint, it stopped being violated.
What's next for Tacit
- Real-device regression on the App Store build (pairing, signals, notifications).
- Closing the remaining widget edge cases (stale mirrors, missed pushes).
- Localization and a short App Preview video — the two things we deliberately left out to ship on time.
Log in or sign up for Devpost to join the conversation.