Solum - Your Records, Your Phone, Nobody Else's
A privacy-first logbook and calculator for anything you self-administer. Reconstitution math, vial tracking, schedules and compliance - all stored on device, with no account and no cloud sync.
- React Native
- Expo
- Cloudflare D1
- Astro
- Privacy
The Problem Statement
Anyone self-administering a compound ends up doing the same arithmetic over and over: how much diluent went in, what the resulting concentration is, how many units that dose works out to on a U-100 syringe, and how much is actually left in the vial. Most people do it in a notes app and a calculator, and occasionally get it wrong.
The apps that exist to solve this almost universally want an account. That means a server somewhere holds a record of exactly what you take and when - which, for this category, is about as sensitive as data gets. Worse, several of them assume they know what you’re taking, with fixed compound lists and built-in “recommendations” that shade into medical advice nobody asked for.
I wanted the opposite of that: do the maths properly, make no assumptions about what’s in the vial, and never send any of it anywhere.
The Solution
Solum is a logbook and calculator for iOS and Android. Everything lives in a local SQLite database on the phone. There is no sign-up, so there is nothing to breach and nothing to reset.
The core of it:
- Vials - compound names are free text, so the app makes no assumptions. Reconstitute with your own numbers, watch remaining volume, and run one vial out into the next without losing its history.
- Draw math - concentration, volume and syringe units computed as you type, for U-100, U-40 or any custom scale. A flag warns you when a draw is too small to measure reliably.
- Log, schedules and protocols - one tap per administration, recurring or finite courses with local notifications, and multi-compound protocols grouped into phases.
- Compliance and observations - a calendar and streaks built from your log alone. No inferences, no correlations drawn on your behalf.
- Export - full JSON or CSV whenever you want it, plus end-to-end encrypted transfer when you move to a new phone.
Privacy as a Published Table
The part I’m most pleased with isn’t a feature, it’s the privacy page. Every request the app will ever make fits in a single table: what triggers it, what’s in it, and what is never in it. There’s no analytics SDK, no crash reporter, and nothing that phones home in the background.
That constraint drove the architecture. The mobile client never calls the backend for anything to do with your data - the backend exists only for referral attribution, subscription validation and config flags. Referrals use a one-way hash of the device ID so a referral can’t be double-counted, and that hash is deleted once the referrer is paid.
The AI Assistant, Done Without a Server
Version 1.2.1 added an assistant that can answer questions about your own logbook and draft vials, schedules and protocols from your numbers. Normally that would mean shipping your data to whoever runs the model.
Instead, it’s bring-your-own-key. You connect your own provider, and messages go from your phone straight to them under your key and their policies. Solum runs no model, holds no key, and never receives any of it. Activity chips in the UI show exactly which lookups the assistant made and what was sent, and every proposed change is reviewed by you before it’s applied.
The Stack
- Expo / React Native with TypeScript for the mobile client, with OTA updates via Expo Updates.
- Zustand for state, expo-sqlite (SQLCipher-backed) for local storage.
- Astro full-stack on Cloudflare Workers for the referral dashboard and attribution backend.
- Cloudflare D1 for the backend database, with scheduled exports to R2 for backups.
- tRPC embedded in an Astro API route for type-safe calls.
- RevenueCat for subscription validation via webhook ingestion.
- Turborepo + pnpm monorepo, with shared
calcandtypespackages so the dose maths and Zod schemas are identical across app, dashboard and tests. - Vitest throughout - the calculation package is TDD from the first commit, because it is the one part of this that genuinely must not be wrong.