DEV Community

Cover image for The honest split: how a Korean solo developer shipped a privacy-leaning save app without claiming "100% on-device"
Yun Lee
Yun Lee

Posted on

The honest split: how a Korean solo developer shipped a privacy-leaning save app without claiming "100% on-device"

I shipped CatchNote on iOS and Android this past month. It is a save-anything app — links, PDFs, screenshots, plain notes — AI sorts everything into categories, OCR makes images searchable, and you find it later by typing what you half-remember.

The privacy story is the moat. But the privacy story I can actually defend is narrower than "100% on-device" — and that is what this post is about.

The problem

2024 was a bad year for my links. Articles forwarded in Slack threads. Blog posts saved as Chrome tabs I never closed. Screenshots of screenshots. The save apps I tried — Pocket (RIP July 2025), Raindrop, Omnivore, Readwise — each one had a setup ceremony. Tags, folders, sync rules, accounts. By week two I always stopped opening the app.

The friction was not the saving. It was the account creation that every save app placed in front of the first save.

The "no account" decision

The first prototype had cloud sync via a hosted backend. I burned a weekend on it and threw it away. Three reasons:

First, account creation kills onboarding. Every step before the first save is a step the user might skip. I have done this myself many times.

Second, cloud sync forces a trust posture I could not defend honestly. "Your data is encrypted in our cloud" is a sentence that has aged badly for many companies. I did not want to write a version of that I would regret later.

Third, the audience that wants a save app most also wants the least surveillance. Cloud-by-default would have shipped to the wrong users.

So — no accounts, no user-data backend, no cloud copy of your saves.

The temptation to claim "100% on-device"

The cleanest marketing line would have been: "everything happens on the phone, nothing leaves." I actually drafted that version of the copy. Then I built the app, and I had to make a categorization decision that broke the line.

I prototyped a fully on-device classifier. On iOS, the model size I could ship gave acceptable quality. On Android, the size-vs-quality trade was wider than I wanted to put my name on. The category drop in quality was visible to me as a user, which means it would be visible to users.

Two options:

Ship a worse-feeling Android app to preserve the "100% on-device" line. Or make categorization a remote inference call and stop saying "100%."

I picked option two. I lost a marketing line. I gained an app that categorizes well on both platforms and a privacy claim I can defend on a packet capture.

The honest split (what travels vs. what stays)

This is the part I would want other indie developers shipping privacy-leaning apps to look at. The wording matters more than it seems.

What stays on the device: the full article body, the screenshot, the note text. All of it in a SQLite database on the phone. The assigned category once it returns. All retrieval, search, reading.

What leaves the device, once per save: a small metadata payload. URL, page title, a short snippet — typically a few hundred bytes. It goes to an inference API for categorization. Stateless call. The provider does not retain the payload for our app.

What never travels: the article body, the screenshot, the full note text, a cross-save graph or activity log, and telemetry of any kind. The app does not have an analytics SDK, including no crash reporter that phones home.

What is not stored server-side: there is no user-data backend. No accounts. No "your CatchNote" sitting on a server we operate. The persistent store of your saves is the SQLite file on your device.

The wording is not elegant. It does not fit on a billboard. But every clause is a clause I can defend if a user inspects the network traffic, which is what matters.

The architecture, briefly

iOS: Swift + SwiftUI. Android: Kotlin + Jetpack Compose. Local storage: SQLite per platform — no cross-platform abstraction, each codebase is small enough to maintain twice. Categorization: remote inference call via OrangeAI's inference layer. Auth: none. Analytics: none. User-data backend: none.

Infrastructure cost today is mostly inference at low volume — plus the platform fees ($99/yr Apple, $25 lifetime Google). When usage scales, inference scales with it. That is the real cost line.

What can be saved (and how OCR fits)

CatchNote handles four kinds of input from the share sheet: links, plain text/notes, screenshots, and PDFs.

PDFs save into the SQLite database with their text extracted for search. Screenshots and other images run through OCR — on the phone, no network call — so what would otherwise be opaque image files become first-class searchable content.

This was important to me as a user. A save app that cannot handle PDFs forces you back to bookmarks. A save app that cannot read images leaves screenshots as black boxes you can never find again. CatchNote handles both.

OCR running locally also keeps the honest split coherent: the screenshot and its extracted text both stay on the device. Only the small metadata payload (URL or title-equivalent, short snippet) travels for the AI category — never the OCR'd content body or the image itself.

What the trade-off actually costs

No cross-device sync. This is the obvious one. I have CatchNote on two phones and I save things twice sometimes. Every time I think about adding sync, I come back to the same place — it re-introduces every problem I built the app to escape.

Categorization needs network. Save works offline; the item lands in SQLite immediately. The category just queues until the device is back online. Most people do not notice. Still worth mentioning.

What I am still uncertain about

Should categorization move on-device on Android eventually? Quality is the bottleneck today. I think small classification heads get there in 12-18 months. The question is whether shipping the remote call now and migrating later is worse than waiting for a fully local launch. I think shipping is the correct decision, but I am open to hearing why I am wrong.

Should I open-source the categorization client? Just the part that builds and sends the payload, calls the endpoint, and writes the category to SQLite. Then people could verify what travels. The attack surface is small. I am leaning yes, no urgency.

Is the split-architecture story understandable to non-technical users? The early reviews suggest people either over-trust ("it is 100% local!" — no) or under-trust ("it is all cloud!" — also not). The truth is in between, and I have not found the one-sentence version.

Numbers so far

iOS launched April 29 (about 13 days at post time). Android launched May 10, after 26 days in Google review (first week of Android at post time). Total installs: 66 (55 iOS, 11 Android). Marketing spend: $0.

Why I am writing this here

Many "privacy-first" indie launches I have read use stronger phrasing than their architecture deserves. I have done it. The audience rewards the line, not the audit — but the audience also leaves the moment they realize the line was bigger than the truth.

The version I am running with now — local saves plus a metadata-only categorization call — is the version I can keep telling. I would rather have a slightly less impressive sentence I can defend for years than a maximalist one I have to take back the first time someone runs Wireshark.

Try it

iOS: https://apps.apple.com/app/id6762549430?ct=week5_devto

Android: https://play.google.com/store/apps/details?id=com.orangeai.catchnoteapp&utm_source=devto&utm_medium=organic&utm_campaign=week5_devto

If you have shipped a privacy-leaning app and wrestled with the same "what claim do I actually deserve" question, I would love to compare notes.

— Interface zero

Top comments (0)