On February 15th, islet was a Python script that polled Nightscout every 60 seconds and stored the results in SQLite. Nine days and 86 commits later, it runs as a self-hosted platform: its own ingest API, analytics engine, relay system, and a native iOS app on my phone. Nightscout polling is off. The only remaining dependency is a relay for the second phone.

Safety note: islet is a personal project and is not medical advice. It does not make dosing decisions. PCU values are informational only and must not be used as dosing advice.

That trajectory was not planned as a single arc. Each phase solved the next most important problem, and each could be built quickly without rewriting what came before.

The phases

Phase 1 — Ingest
Nightscout polling, SQLite storage, backfill, CLI, systemd daemon. One session from spec to running service.
Phase 2 — Analytics
Glucore engine: insulin on board, carbs on board, blood glucose impact, deviation analysis, model-based 30-minute predictions.
Phase 3 — Independence
Direct ingest API, per-device tokens, conditional relay, three ingest modes. Nightscout becomes optional infrastructure.
iOS companion
Native SwiftUI app. Glucose dashboard, AI-assisted food logging, meal lifecycle, Warm Amber theme.

Phase 3.3 — the actual cutover to API-only ingest — went live on the 23rd. Three commands, no data gap, both phones continued uploading. The previous post described the design that made this boring. On the day, it was boring.

Where it stands now

5,823
Python SLOC
1,608
Swift SLOC
641
tests passing
86
commits

The server runs 24/7 on a Raspberry Pi 5B. The API handles ingest from two phones, serves analytics to the iOS app, provides AI meal estimation, and relays selectively to Nightscout. The test suite covers the ingest pipeline, analytics engine, API routes, and meal estimation endpoint.

What having a client changes

Before the iOS app, islet was invisible. It ran on a Pi in the next room, processing data that could only be seen through curl or the CLI. The system worked, but interacting with it required thinking like a developer.

The app makes islet tangible. You can glance at your glucose, check your active insulin, log what you’re eating, review recent meals. The information that was always being computed is now accessible without context-switching into a terminal.

Infrastructure that nobody can see is infrastructure that nobody trusts.

That changes the relationship with the project. It moves from something you maintain to something you use. The feedback loop tightens: problems that would take hours to notice via logs become obvious in seconds when you’re looking at stale data or a wrong prediction on your phone screen.

What didn’t go as expected

The server-side meal estimation endpoint was harder than the iOS UI. SwiftUI made the client straightforward — views are declarative, the network layer is a single actor, the state management is built in. But making the API response shapes match what Swift’s Codable decoders expected took several iterations of fix, build, test, repeat.

The other surprise was data staleness. A glucose reading from 45 minutes ago, displayed without any visual indicator that it’s old, is worse than showing nothing. The server already guards against stale data in its analytics — the safety contract warns at 15 minutes and refuses predictions at 60 — but the lesson applies to display too. Data age needs to be as visible as the reading itself.

What comes next

The remaining Nightscout dependency is the relay for the second phone. Once that phone can consume islet data directly — either through its own app integration or through the iOS companion — the relay can be turned off and Nightscout decommissioned.

Beyond that: glucose charting in the app, longer-range trend analysis, and the slow process of replacing everything that currently points at Nightscout with something that points at islet instead.

The destination was always a self-contained system. Eighty-six commits in, the outline is visible.