Files
jeanlucmakiola.de/src/content/blog/no-internet-permission.md
Jean-Luc Makiola d1acda5a93 Add Datenschutzerklärung, two blog posts, and a /uses colophon
- datenschutz.astro: DSGVO privacy policy (server logfiles, Hetzner as
  Auftragsverarbeiter per Art. 28, cookieless Umami, self-hosted fonts,
  data-subject rights, supervisory-authority complaint).
- consts.ts: extract shared LEGAL entity data; Impressum now reads from it.
- blog: "Why my calendar app has no internet permission" and
  "Open standards as a constraint, not a checkbox".
- uses.astro: colophon of the site stack, Floret apps, and self-hosted infra.
- Footer: add Uses + Datenschutz links alongside Impressum.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 14:54:49 +02:00

68 lines
3.3 KiB
Markdown

---
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.