Dainvo is an Electron desktop app with a local-first calendar backend. The renderer presents data through React and FullCalendar, while the Electron main process owns persistence, provider sync, OAuth, and trusted platform access.
The Electron main process is the trusted backend boundary. It owns:
SQLite and provider SDK/network calls must stay in the main process. The renderer must not open database files, call Google/Microsoft/CalDAV directly, or receive OAuth tokens.
The preload layer exposes a narrow window.calendarApi object to the renderer.
The current scaffold uses contextIsolation: true and nodeIntegration: false.
Preload is intentionally narrow and does not expose Node, Electron primitives, or
raw ipcRenderer; if preload is later bundled into a single file, Electron
sandboxing can be revisited.
Responsibilities:
ipcRenderer.The renderer is a React app focused on user experience:
FullCalendar is a renderer and interaction layer only. It fetches visible events through typed application APIs and reports edits through callbacks. The app’s services persist those changes.
The application service layer contains provider-neutral calendar behavior:
CalendarServiceEventRepositoryCalendarRepositoryRecurrenceServiceSyncServiceDocumentServiceProviderAdapter interfaceThe local database is the source of truth/cache for UI rendering. Provider sync adapters reconcile remote calendars with local records.
Local recurring events store an iCalendar-compatible RRULE string on the
master event. CalendarService.listEvents expands recurring masters only for the
visible requested range and returns synthetic instances for the renderer.
Instance-level exceptions and edits are intentionally deferred; editing a
recurring event updates the whole series.
The current recurrence expansion uses stored ISO start/end timestamps and UTC date arithmetic. Full provider-grade timezone and DST parity is deferred to the later recurrence/sync milestones.
Provider-specific behavior belongs behind adapters:
LocalCalendarAdapterGoogleCalendarAdapterMicrosoftGraphCalendarAdapterCalDavAdapterAdapters map provider-specific calendar and event payloads into provider-neutral domain objects. They must be mockable and must not be called from renderer code.
The CalDAV adapter uses tsdav in the main process for account discovery and
calendar-object fetches, then parses VEVENT payloads with ical.js. The current
CalDAV implementation is read-only and uses full object reconciliation for later
syncs because CalDAV server delta behavior varies by provider.
window.calendarApi for calendars and events.This keeps rendering, persistence, and sync responsibilities separate.