Inspiration
Texting a photo takes a second and is forgotten just as fast. A postcard is different: someone chose a picture, wrote a few words by hand, and sealed it for you. When we saw iPhone Duo, we realized the phone's body already makes the postcard gesture. You open a card to write it and close it to seal it. Sable brings that ritual back for the people you love, whether that's Grandma, a friend, or a partner far away.
What it does
- Pick a photo from your trip. It becomes the front of a vintage postcard: cream paper, dark green ink, a vermilion stamp.
- Unfold your iPhone Duo and the card turns over to its back, where you write your note and choose who it's for.
- Fold it closed and the card is sealed with a stamp and a soft haptic thud.
- Tap Send and it goes straight to the recipient's Sable inbox, where they turn it over to read your words.
Folding never sends anything. Only the Send button does. On ordinary iPhones, buttons do the same thing as the hinge.
How we built it
Four people worked in parallel from shared written contracts: the Swift types, the service protocol, the JSON wire format, and file ownership. That way nobody blocked anybody.
- iOS app (SwiftUI, iOS 27.1 SDK): an observable main-actor controller turns native hinge events (
onHingeChange,DeviceHingeContext) and button taps into card states: front → writing → sealed → sending → sent. Drafts survive relaunches, and PhotosPicker images are converted to JPEG before upload. - UI and motion: screens that take plain values and callbacks, with no networking or hinge code inside. A reusable 3D card flip turns into a crossfade when Reduce Motion is on. The screens support Dynamic Type, VoiceOver and keyboard-visible editing.
- Backend (Supabase): Auth-linked profiles, one conversation per pair of people, immutable postcards, and Row Level Security on every table. Photos live in a private Storage bucket that only the sender and recipient can read, through signed links. Realtime tells the recipient's inbox to refresh. Sending is a single transactional function with idempotency keyed on the draft's ID.
Challenges we ran into
- No hardware yet. Everything runs on the iPhone Duo simulator, so we built button fallbacks for every hinge action and kept "fold" and "send" strictly separate.
- Retries under pressure. Our backend tests caught a race: 20 identical sends at once occasionally raised a raw database error instead of returning the one stored postcard. We fixed the constraint design, and the stress test now passes run after run.
- Privacy by default. No contact scraping and no public directory. You find someone only by their exact username, and email is never exposed.
- Four parallel workstreams in one day. Contracts first, integration last.
Accomplishments that we're proud of
- A backend verified end-to-end against a real local Supabase stack: 18 automated tests with a sender, a recipient and an outsider. They cover account security rules, photo privacy, spoofing attempts, validation, idempotent and concurrent sends, and realtime isolation.
- An interaction where the phone's hinge is the interface, and it can never send by accident.
What we learned
Designing around a new form factor means designing for its absence too: every hinge moment needs a button twin. Writing the contracts before the code let four people build at once.
Where it stands
- Working and tested: the backend (database, security rules, photo storage, realtime).
- Written and unit-tested against stand-in packages: the app's state controller and the UI screens.
- In progress at submission: the shared Swift packages and the final integration build.
What's next for Sable
Finish integrating the full app. Then add printed postcards mailed to a real address, and shareable links for people who don't have the app yet.
Built With
- docker
- ios
- iphone-duo
- javascript
- node.js
- postgresql
- postgrest
- row-level-security
- supabase
- supabase-auth
- supabase-realtime
- supabase-storage
- swift
- swiftui
- xcode
Log in or sign up for Devpost to join the conversation.