--- title: Why my calendar app has no internet permission description: >- Calendula can't talk to the network — and that's the whole design. A look at building on Android's CalendarContract instead of reinventing a sync stack. pubDate: 2026-06-28 tags: [android, architecture, calendula] draft: false --- Open Calendula's manifest and you'll notice something missing: there is no `android.permission.INTERNET`. The app physically *cannot* reach the network. For a calendar — a category of app practically synonymous with cloud accounts — that sounds like a missing feature. It's the opposite. It's the design. ## The usual shape of a calendar app Most calendar apps own their data. They sign you into an account, pull events down over the provider's API, cache them in a private database, and reconcile changes with their own sync engine. That sync stack is the hard part: conflict resolution, recurring-event expansion, time zones, retries, token refresh. It's also the part that locks you in — your events live in *their* schema, reachable only through *their* app. ## The other option Android already gives you Android ships a system calendar database, exposed through [`CalendarContract`](https://developer.android.com/reference/android/provider/CalendarContract). Anything synced to your device lands there: a CalDAV account via [DAVx5](https://www.davx5.com/), your Google calendar, a local on-device calendar, a read-only WebCal subscription. They all show up through the same content provider, with the same columns. Calendula is a pure front-end over that provider. It reads events through `CalendarContract`, and when you create or edit something, it writes straight back. Whatever sync adapter put the calendar on your device picks the change up and pushes it out. There is **no own database and no reinvented sync stack** — so there is nothing for the app to phone home about. ## What you get for free Dropping the network permission isn't a sacrifice; it's what falls out of the architecture: - **Your data stays yours, and stays portable.** Events live in the platform's store and in your CalDAV account — not in a schema only Calendula understands. - **Privacy is structural, not a promise.** Zero telemetry and zero analytics are easy to claim. *No internet permission* is enforced by the OS: even if I wanted to exfiltrate your schedule, the app couldn't. - **Reminders still work** — Calendula delivers them itself as notifications, because Android delegates reminder delivery to the installed calendar app. - **Any account "just appears."** Add a new CalDAV account in DAVx5 and it surfaces in Calendula with no integration work, because the integration point is the OS, not a vendor API. ## The trade-off, stated honestly A front-end can only be as good as the provider beneath it. Calendula doesn't add its own server-side features, and it relies on a sync adapter like DAVx5 being installed to actually move bytes. That's a deliberate line: I'd rather put a thoughtful Material 3 Expressive interface on an open protocol than own a sync stack I'd inevitably get subtly wrong. The same idea drives the rest of the [Floret family](/work) — Agendula is the exact same bet, made on the OpenTasks provider instead of the calendar one. Different content, identical philosophy: build the part that's worth building, and let open standards carry the rest.