-
-
Letters, not notifications. New messages arrive as envelopes. Tap to turn one over and read what someone wrote for you.
-
Keep or let go. Stamp each letter KEEP to save it in your book, or LET GO to release it.
-
Your goal, your circle. Set a goal like "Master Spanish verbs," count down the days and read every message your friends send along the way.
-
You made it. Finish your goal, celebrate, and turn everything they wrote into your book with one tap.
-
Your journey becomes a book. Every letter you kept is bound into a keepsake book of the people who cheered you on.
-
Earn pins as you go. Collectible pins celebrate milestones, like writing your first message in your own hand.
-
The moment it arrives. A letter from your circle lands on your lock screen at 7 AM, right when you need it.
Inspiration
I live in Japan. My family doesn't.
On the hard days, what keeps me going is a message from them. A "good luck tomorrow" from my mom, a voice note, a photo of the dog. And every one of those messages ends up buried in a chat, under hundreds of others, until one day I can't find it anymore.
We almost never keep the words that matter most. So I built Kotozute (言伝, a message entrusted to someone to deliver): you set a goal, your people write to you, and each message arrives at the moment they chose. The morning of the race. The night before the exam. Or sealed, until the day you need it.
What it does
- One link for everyone. You share a single link. People with the app join your circle; people without it write to you from a web page, no account needed.
- Messages that arrive on time. The sender chooses the minute. The message lands as a notification and on your Home and Lock Screen widgets.
- Sealed letters. A capsule stays closed until a date, or until you decide. It arrives tied with a red ribbon, and you open it by swiping across the ribbon to cut it.
- In their own hand. People can write by hand, with brushes, stamps and a little neon. You watch their handwriting appear stroke by stroke, at the speed they wrote it.
- Nothing gets lost. You swipe to keep or let go. What you keep goes into a folder for that person. When the goal is done, every kept message becomes a printable book.
- Pins for the people who write. Enamel pins earned only by writing to someone: First word, Seven mornings, Sealed. They are never for sale.
How I built it
Kotozute is a native SwiftUI app (Swift 6, iOS 17+) with no backend of my own. These are personal messages, and I didn't want to be the one holding them. Everything lives in the user's own iCloud.
- SwiftData + CloudKit for the private store. SwiftData has no
CKShare, so sharing uses raw CloudKit: each goal gets its own record zone, shared with a zone-wideCKShare. - Guests without the app write through a small Next.js page on Vercel. It signs requests with a CloudKit server-to-server key and drops the message into a temporary mailbox in CloudKit's public database. The owner's app moves it into their private iCloud and deletes it from the mailbox.
- RevenueCat for the subscription and the paywall. The rule is whoever pays unlocks their circle: the person who writes a chain or a capsule pays, the person receiving it never does.
- On-device AI only: Foundation Models for message suggestions and tone, Vision to crop covers around faces. Every AI feature has a non-AI fallback.
- One
MessageCardrenders the same in the app, the widget, the Live Activity and the PDF book. - Handwriting is recorded as timed strokes and replayed with
CanvasandTimelineView. The same painter draws it in the widget and in the book. - Animations are native SwiftUI (3D flips, the folder that opens on its hinge, the ribbon you cut) plus a few Lottie files I generated from code. Sounds were designed with ElevenLabs.
I built it solo in about four weeks, with Claude Code as my pair programmer.
Challenges
- Sharing without a server. CloudKit hides participants' names behind public links, so members showed up as "Someone". I added a small
SharedMemberrecord that each person publishes about themselves. - Production is not Development. CloudKit creates fields automatically in Development but not in Production. A missing field made link creation fail with a useless "Atomic failure". The app now surfaces the real error, and I deploy the schema before every build.
- App Review, twice, for the same guideline (3.1.2(c)). First the paywall mentioned a free trial that didn't exist yet in App Store Connect. Then, once the trial was real, the word free was louder than the price. The fix was making the billed amount at least as prominent as the trial, everywhere.
- Making paper feel like paper without real 3D: perspective, honest shadows, and faces that switch exactly when a card is edge-on.
What I learned
- Privacy-first and zero-cost can be the same decision, but you pay for it in complexity.
- Most of the design work was deciding what not to show. A friend tested an early version and thought it was a goal tracker. The fix was copy and placement, not a new feature.
- Recognition should reward giving, not consuming. That's why the pins go to the people who write.
What's next
- Printed books, as a one-time purchase.
- Pins that the receiver can give back: Kept, Bound, Made it.
- More languages beyond English, Spanish and Japanese.
Built With
- activitykit
- apple-intelligence
- cloudkit
- elevenlabs
- foundation-models
- icloud
- ios
- lottie
- next.js
- pdfkit
- revenuecat
- storekit
- swift
- swiftdata
- swiftui
- typescript
- vercel
- vision
- widgetkit
- xcode
- xcodegen
Log in or sign up for Devpost to join the conversation.