Release 2.20.0. **Added** - Long-press an event's title, location or description to copy it ([#195]). - Settings → About lists the open-source projects Calendula ships, with copyright holder, licence and a link to each project's source ([#281]). **Changed** - Week and day view seat every hour in its own rounded cell instead of drawing a separator line across the column; an on-the-hour event fills its cell rather than overhanging the seam ([#113]). - Event titles run to the edge of their chip in all three grid views — no ellipsis. RTL keeps it, where clipping would cut the start of the title ([#164]). - Month events show their start time where the chip is wide enough, and event times across month, week and day are set in a regular weight ([#219]). - An invitation you haven't answered is drawn as an outline; declined events keep their filled, struck-through chip and now sort last in the month view ([#230]). - The top-bar title falls back to a shorter form instead of being cut off, and the bar's trailing edge lines up with the grid under it ([#165]). - The jump-to-today button carries today's date and rolls over at midnight ([#220]). - The quick-switch pill hides when there is nothing to switch between, and views can now be turned off down to a single one ([#150]). **Fixed** - A long location wraps and its card grows, instead of scrolling sideways out of sight ([#273]). - The event form capitalizes sentences again; location stays uncapitalized, being as often a URL as an address ([#146]). - A dragged block's floating copy wraps its time and title the way the block does, instead of clipping to one line while held ([#267]). ### Release preparation `versionName`/`versionCode` → 2.20.0/22000, `CHANGELOG.md`'s Unreleased section moved under a dated 2.20.0 heading, and a hand-written 497-character `fastlane/metadata/android/en-US/changelogs/22000.txt`. Six of the merged PRs had no CHANGELOG entry (#146, #150, #195, #230, #267, #281); they are written up here. The existing #164 entry only described the month view and did not mention the RTL exception — both corrected. ### Also here `scripts/check_changelog_lengths.sh`, run in CI next to the reproducible-release invariant. Play rejects a "What's New" over 500 characters, which would fail the upload *after* the release had already shipped to F-Droid and Codeberg — 2.19.4 went out at 697. The script walks every locale, fails on the current `versionCode` and only warns on the already-published files, of which 13 are over the limit from when the pipeline auto-generated them from `CHANGELOG.md`. Deviation worth naming: this does not fix those 13. They are published and Play never re-reads them, so failing on them would paint every PR red for no gain; `--strict` covers them if they are ever backfilled. Follow-up filed as #285 — the store listing exists in only 4 of 12 locales and its graphics still don't qualify for Play. All twelve issues above are closed by their own PRs; this branch ships them. Co-authored-by: Jean-Luc Makiola <business@jeanlucmakiola.de> Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/286
Calendula
A modern Material 3 Expressive calendar for Android.
Reads, writes, and reminds — on top of the system calendar, with zero network access.
Calendula is named after the flower whose name — like the word calendar —
comes from the Latin kalendae, the first day of the month. It lives
entirely on top of Android's CalendarContract: any calendar synced to your
device (CalDAV via DAVx5, Google, local, WebCal subscriptions, …) simply
appears, and everything you create or edit syncs back the same way. No own
database, no sync stack reinvented.
✨ Features
Calendar
- Month, week, and day views with a one-tap view switcher
- Full event details — attendees and their responses, reminders, recurrence (humanized), availability, visibility, foreign time zones
- Per-calendar visibility toggle, grouped by account
Editing
- Create, edit, and delete events — including recurring events with scoped writes: only this event, this and all following, or the whole series
- Recurrence picker with one-tap presets and custom rules (interval, weekday toggles, end conditions); rules it can't express are preserved verbatim
- Conflict-safe saves: if an event changed elsewhere while you were editing, Calendula asks instead of silently overwriting
- Read-only calendars (WebCal, birthdays) are detected and respected
Reminders
- Event reminders delivered by Calendula itself as notifications — essential when it's your only calendar app, since Android delegates reminder delivery to calendar apps
- Tap a reminder to land on the event
Design & privacy
- Real Material 3 Expressive throughout — dynamic color (Android 12+), expressive motion and shapes, light/dark theme
- English and German UI plus community translations (Spanish, French, Italian, Polish, and more in progress), per-app language setting — and open to more languages
- Zero telemetry, zero analytics, no internet permission — your data never leaves the device
📦 Install
Pick whichever channel you already use — they all install the same app:
| Channel | Updates | Notes |
|---|---|---|
| Official F-Droid | On F-Droid's build schedule | Recommended; no extra setup |
| Self-hosted F-Droid repo | Minutes after a release | Fastest; needs the repo added once |
| Codeberg release / Obtainium | Per release | Plain APK download, or automated by Obtainium |
| Google Play | Per release | Signed with Google's key — see below |
| Build from source | Whenever you build | Full control |
F-Droid (recommended)
Calendula is on the official F-Droid repository — just search for Calendula in any F-Droid client, or install it from f-droid.org.
F-Droid rebuilds from source on its own schedule, so a new version usually shows up there a few days after release.
Self-hosted F-Droid repo (fastest updates)
Every release is built, signed, and published to a self-hosted F-Droid repository as part of the release pipeline, so it lands there first. Add it once and your F-Droid client handles updates from then on:
-
In your F-Droid client, open Settings → Repositories → Add (or open the link below on your phone):
https://apps.dev.jeanlucmakiola.de/dev/fdroid/repo?fingerprint=C2C0640402BF458FC0ED957AF0B37AA4C14022E72F89CE90B5965B458CF73425Repo:
https://apps.dev.jeanlucmakiola.de/dev/fdroid/repo· fingerprint (SHA-256):C2C0 6404 02BF 458F C0ED 957A F0B3 7AA4 C140 22E7 2F89 CE90 B596 5B45 8CF7 3425 -
Refresh, search for Calendula, install.
Codeberg release / Obtainium
If you'd rather not use F-Droid at all, every release is also published on
Codeberg with the
signed APK (calendula_vX.Y.Z.apk) and a .sha256 checksum attached — download
and install it directly.
For automatic updates from that channel, use
Obtainium — on the phone,
add Calendula in one tap,
or do it by hand: Add App → paste https://codeberg.org/jlmakiola/calendula
→ Add. Either way, Obtainium tracks the releases and prompts you when a new
one appears.
Google Play
Calendula is live on Google Play: play.google.com/store/apps/details?id=de.jeanlucmakiola.calendula.
Play builds are signed with Google's key rather than mine, so switching between Play and any other channel requires an uninstall (and with it, a fresh start for app settings — your events live in the system calendar and are unaffected).
Build from source
The build is a plain Gradle build with no proprietary dependencies — see
docs/BUILDING.md (note the floret-kit submodule).
Official F-Droid, the self-hosted repo, and the Codeberg releases all share the same signing key, so you can switch freely between them without reinstalling. Google Play is the exception — see above.
📚 Documentation
- Contributing — how to report, propose, and patch
- Building from source — requirements and Gradle tasks
- Architecture — the layered design and key pipelines
- Milestones — what's shipped and what's next
🤝 Contributing
Bug reports, ideas, and patches are all welcome on Codeberg.
The short version: start with an issue. Features get a yes-or-no before they
get code, and both features and bugs are assigned a milestone whose
release/vX.Y.Z branch your pull request then targets. Typo and docs fixes can
skip straight to a pull request. Translations don't go through pull requests at
all — Weblate owns them.
Read CONTRIBUTING.md before writing code: it covers the
workflow, the build (note the floret-kit submodule), and the architectural
rules a change is reviewed against.
🌍 Translations
Calendula ships in English and German, with community translations in Arabic, Chinese, French, Italian, Polish, Portuguese, Russian, and Spanish at varying degrees of completeness — partial is fine, untranslated strings simply fall back to English. You're warmly invited to add or finish your language. Translations are managed on a self-hosted Weblate:
No coding needed — register on the Weblate server, pick (or request) a language, and translate the strings in your browser. You can also reach this link in the app from the top of Settings → App language.
📜 License
MIT — Jean-Luc Makiola, 2026









