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>
This commit is contained in:
67
src/content/blog/no-internet-permission.md
Normal file
67
src/content/blog/no-internet-permission.md
Normal file
@@ -0,0 +1,67 @@
|
||||
---
|
||||
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.
|
||||
Reference in New Issue
Block a user