Rejog Stash: Your Stuff, Findable and Lendable
Point your camera at a shelf; it catalogs what it sees. Then lend to a friend with one link, no app, no account.
The Problem
You own lots of things and can’t find the one you want, and you readily lend things to friends and invariably forget who had it last. I wanted the friction gone on both ends: catalog what you own, and enable a way to share it without losing track of where it ended up.
What I Built
A personal inventory app with peer-to-peer lending. Photograph a shelf and it becomes a searchable list, each item remembering where you last saw it. Lending is a one-time link, and the borrower needs no app and no account.
Three codebases - native iOS, native Android, and a Cloudflare Worker for the web side - that share no model and no code. What they share is a wire contract: one versioned, additive-only definition of every request and response, owned by the Worker and matched byte for byte by both platforms. iOS is the authority on how a feature is implemented, and Android ports but remains a native look-and-feel. The Worker is the authority on what the network looks like. When they disagree, the contract wins.
Tech Stack
- Swift
- Kotlin
- TypeScript
- JavaScript
- HTML/CSS
- SQL
- Python
- iOS SwiftUI
- Android Jetpack Compose/AndroidX
- Cloudflare Workers
- static browser frontend
- CameraX
- iOS SwiftData + CloudKit/private DB + Keychain/iCloud Keychain
- Android Room/SQLite + DataStore/EncryptedSharedPreferences
- Cloudflare D1/KV/R2
- XcodeGen/TestFlight/App Store Connect scripts
- Gradle/R8/Firebase App Distribution/Play tracks
- Wrangler/Workers Assets/custom domains
- D1 migrations
- iOS Vision/Core ML MobileCLIP/FoundationModels/OpenRouter relay
- Android ML Kit/ONNX Runtime Mobile/MobileCLIP model download
- Worker api-router relay to OpenRouter
- XCTest/XCUITest
- Android JUnit/Robolectric/Compose UI tests/MockWebServer
- Vitest/node:sqlite
- Playwright
- Python device integration harnesses
- StoreKit 2
- Play Billing
- APNs/FCM/Web Push
- Resend
- osmdroid
- Retrofit/OkHttp/kotlinx.serialization
- Coil
- ZXing
How It Works
Capture is camera-first. On iOS, Vision instance segmentation pulls every object out of one frame as its own item, running off the main actor under Swift 6 strict concurrency. Android does the same job with ML Kit subject segmentation off a CameraX feed. Naming routes through an owner-authenticated identify relay so no API key ever rides the wire, with an on-device model as fallback; on-device Foundation Models are where this wants to land, and that path already works against the iOS 27 beta. Search is semantic either way - embeddings plus a synonym map - so “coat” finds your windbreaker.
One Worker (D1, KV, R2) is the meeting point, serving four trust domains from a single codebase: an owner’s phone signing writes with a per-tenant HMAC key, an owner on the web console with a passkey, a borrower with no account authorized purely by holding an unguessable link, and an internal operator. The borrower is the interesting one - identity is possession of the secret, and nothing more.
Privacy is enforced in the code, not in a policy line. On Android, borrowed items live in a physically separate, device-local database that structurally cannot reach an upload path, pinned by a boundary test. Location is read only in the foreground, at the moment of capture, to stamp where an item was last seen - never in the background. Contact details cross between two people only once a loan is actually established, enforced server-side. The privacy policy is the public version of the same commitments.
What Made It Hard
Getting multi-item recognition to run on-device, fast, and off the main thread. Keeping three genuinely native clients honest against one contract with no shared codebase to lean on - the rule is additive and back-compatible only, so a field can be added but never repurposed or removed once it ships. And enforcing privacy structurally instead of as a promise, which costs more up front and is the only version that survives a refactor.
The Throughline
Take the tedium out of a real chore so the tool disappears and you just get the result. The hard engineering - the contract, the on-device vision, the structural privacy - is all in service of “point and done.”
Status
The borrower web app and backend are live at stash.rejog.net. The iOS and Android apps both run on real devices and are in pre-launch testing. Neither is in the App Store or Play Store yet.