Skip to content

Calendar #5

Description

@michielbdejong

Context

Audit of the current Google Calendar integration, to decide whether it could replace Google's own Calendar UI as the daily-driver calendar. Short answer: not yet — see gaps and phased plan below.

The plugin spans three repos:

  • localthought/atomic-plugins (this repo) — mirror of integrations/, including the undeployed integrations/localthought/calendar-proxy.patch. Work on this plan happens here.
  • ontola/atomic-server — host: LocalThought browser OAuth/PKCE flow, WASM Syncables engine, generic CalendarView UI. See planning/google-calendar-import-gaps.md and docs/imports/google-calendar-gap-report.md there for the existing (thorough) internal audits this plan builds on.
  • localthought/devonian (platform-lenses/google-calendar/) — the actual lens: projection, recurrence, and two-way edit logic (sync.ts, import.ts, lens/*.ts). Pulled in as a pinned GitHub dependency, not vendored.

A companion service, localthought/integration-proxy, also needs a deploy (see Phase 1).

Current status

Import (read path) — solid.

  • Browser-only OAuth/PKCE via LocalThought, no server secrets.
  • Bounded date-range import or "keep recurring series" mode; live-verified against a real Google account (2026-09-09: 22 calendars, 32 events).
  • All-day vs. timed events projected correctly (exclusive end dates, civil-date handling, DST-safe).
  • Recurrence: daily/weekly/monthly/yearly RRULE with INTERVAL/COUNT/UNTIL/BYDAY/BYMONTHDAY/BYMONTH/BYSETPOS/WKST, RDATE/EXDATE, exceptions and cancellations.
  • Auto-refresh every 5 min while a tab is open; stable identity across re-imports; local edits and Atomic-only fields preserved.

Two-way sync — implemented but narrow and not live-deployed.

  • previewCalendarEdits / applyCalendarEdit (devonian sync.ts) cover only 5 fields: name/summary, description, location, start, end — with ETag/If-Match conflict detection, including individual recurring instances.
  • No create-event or delete-event path exists at all — only editing fields on events already imported from Google.
  • The proxy change required for writes (calendar.events scope, If-Match CORS forwarding) is an unmerged/undeployed patch (integrations/localthought/calendar-proxy.patch in this repo). Production OAuth scope is still calendar.readonly, so write-back doesn't function yet even though the client code exists.

Missing outright:

  • No RSVP/attendee management, no reminders/notifications, no conferencing links usable, no calendar colors, no special event-type handling (birthdays, OOO, focus time, working location).
  • No combined multi-calendar agenda/day/week view with per-calendar visibility — each Google calendar becomes its own Atomic table.
  • No incremental sync (persisted syncToken); every refresh is a bounded re-fetch, deletions inferred only from tombstones inside the fetched window.
  • No ICS/CSV import or export.
  • No event-creation dialog / recurrence-authoring UI (raw table-cell edits and raw JSON only).

Why it can't yet replace Google's Calendar UI

  1. No event create/delete from Atomic — anything new or canceled must be done in Google's own UI first, then pulled in on next sync.
  2. Write scope isn't deployed — even editing an existing imported event's time/title doesn't currently reach Google in production.
  3. No reminders/notifications and no RSVP handling — anything involving other people or alerts still needs Google's app.

Phased plan

Phase 1 — Close the write-back gap (small: mostly deployment)

  • Deploy calendar-proxy.patch to integration-proxy (or land it as a real PR there); flip OAuth scope in production; require existing connections to reconnect.
  • Live-verify applyCalendarEdit against a real account (currently mock-tested only).

Phase 2 — Event creation & deletion (medium — the actual blocker)

  • Add insertEvent / deleteEvent to the devonian lens (Google events.insert / events.delete), mapped from new-row / row-deletion in an imported calendar table.
  • Build a proper event editor dialog (title, description, location, start/end, all-day toggle) so projected fields and the outbound payload can't disagree — this is P0 in the existing gap doc too.

Phase 3 — Make it feel like a calendar, not an event table (largest chunk)

  • Unified multi-calendar agenda/week/day view with per-calendar color and visibility toggles, built on existing per-calendar identity.
  • Reminders/notifications (surface Google's reminder minutes; browser notification at trigger time as a stretch).
  • Attendees/RSVP: read-only display first, write-your-own-RSVP as a follow-up.

Phase 4 — Reliability for daily-driver use

  • Incremental sync via Google's syncToken, proper tombstone/deletion handling, recovery from HTTP 410.
  • Recurrence editing UI ("this event" / "this and following" / "entire series") — currently raw-JSON only.

Phase 5 — Nice-to-haves

  • Special event types (OOO, focus time, working location, birthdays) rendered distinctly instead of as generic meetings.
  • ICS import/export as a fallback path independent of the Google API.

Suggested order of work

Phases 1–2 are the minimum to stop needing Google's UI for basic scheduling; Phase 3 is what makes it pleasant enough to actually prefer day to day.


Moved from ontola/atomic-server#1602 — GitHub doesn't support issue transfer across different-owner repos, so that issue was closed with a pointer here.


🤖 Generated with Claude Code

https://claude.ai/code/session_01LjCR6idtt6BFaKCiB3JDnb

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions