Add six draft posts drawn from Calendula issues
Technical, journey, and philosophy posts sourced from the Calendula issue threads, reviewed for source-accuracy, standards, ethics, and voice. All draft:true with staggered future pubDates; they stay hidden in prod until approved (draft:false) and due. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
74
src/content/blog/the-feature-i-said-no-to.md
Normal file
74
src/content/blog/the-feature-i-said-no-to.md
Normal file
@@ -0,0 +1,74 @@
|
||||
---
|
||||
title: The feature I said no to (and the one I found instead)
|
||||
description: >-
|
||||
A user asked Calendula to sync itself to a plain .ics file. Talking it through
|
||||
in the open turned a "no" into a better, smaller feature — and clarified what
|
||||
the app is actually for.
|
||||
pubDate: 2026-07-10
|
||||
tags: [open-source, calendula, open-standards]
|
||||
draft: true
|
||||
---
|
||||
|
||||
One of the more useful things that has happened to Calendula wasn't a feature I
|
||||
added. It was one I turned down — in public, in a comment thread, with the
|
||||
person who asked for it ([#7]).
|
||||
|
||||
The request: let Calendula save its calendar state to a file. Prompt for an
|
||||
`.ics` on startup, write back on every change, so events are never "trapped" in
|
||||
the app. Reasonable on its face. My answer was no — but the interesting part is
|
||||
how we got from there to something I *did* ship.
|
||||
|
||||
## Why it was a no
|
||||
|
||||
Calendula doesn't own your data. It's a client for Android's system calendar
|
||||
provider, and the syncing is left to whatever CalDAV adapter you've already set
|
||||
up — DAVx5, SmoothSync, whatever moves your events today. A "write to an .ics on
|
||||
every change" feature quietly reintroduces the exact thing the app exists to
|
||||
avoid: it starts handling sync itself.
|
||||
|
||||
And live file sync is genuinely hard, for a reason that has nothing to do with
|
||||
effort. The moment two sides can edit the same event — a local change and a
|
||||
synced-in change landing on the same slot — *something* has to decide which wins.
|
||||
CalDAV has machinery for that. The `.ics` format doesn't; it was designed for
|
||||
backups and for handing events from one place to another, not for being written
|
||||
to continuously. Build the feature and you inherit a merge engine you now have to
|
||||
get right forever. As I put it in the thread: as a developer you want a database
|
||||
to talk to, not to hand-roll storage and eat all the hiccups that come with it.
|
||||
|
||||
## Why saying no in the open mattered
|
||||
|
||||
I could have just closed the issue with "out of scope." Instead we talked it
|
||||
through, and the request opened up into something more specific than the first
|
||||
sentence. What the reporter was after wasn't live bidirectional sync — it was a
|
||||
guarantee that their events could exist as a file that isn't hostage to one app.
|
||||
Their words, as we got there: "just a way to automatically write and read into a
|
||||
file without it ever being trapped in the application."
|
||||
|
||||
That's a completely different, and much smaller, feature. Not a sync engine —
|
||||
a **periodical auto-export**: set an interval, and at that interval your
|
||||
calendar is written out to an `.ics`. No merge problem, because it's one
|
||||
direction. No philosophy problem, because export *is* what the format is for.
|
||||
That became [#8], and it satisfied the actual need — "That satisfies me!" was
|
||||
how the thread closed.
|
||||
|
||||
I also pointed them at [ICSx5] and mentioned a separate app, the DAVx5 pattern,
|
||||
would be the honest home for true file sync — because a real solution to their
|
||||
original idea deserves to exist, just not bolted into a calendar client.
|
||||
|
||||
## What the thread was really for
|
||||
|
||||
The trade I keep making is that
|
||||
[open standards are a boundary, not a checkbox](/blog/open-standards): the
|
||||
`.ics` request sat just outside that boundary, and holding the line kept the app
|
||||
simple enough to stay trustworthy. But the lesson wasn't "learn to say no." It
|
||||
was that a good "no" is a conversation. The user leaves with something that
|
||||
works, I leave with a sharper sense of what the app is *for*, and the thread
|
||||
stays public so the next person can read the whole reasoning instead of a closed
|
||||
issue with one terse label.
|
||||
|
||||
You don't get that from a roadmap. You get it from taking the request seriously
|
||||
enough to argue with it.
|
||||
|
||||
[#7]: https://codeberg.org/jlmakiola/calendula/issues/7
|
||||
[#8]: https://codeberg.org/jlmakiola/calendula/issues/8
|
||||
[ICSx5]: https://icsx5.bitfire.at/
|
||||
Reference in New Issue
Block a user