UniCalendar

approved

by yinshaohua

A unified calendar view syncing events from Google Calendar, CalDAV, and ICS feeds into one beautiful interface. - This plugin has not been manually reviewed by Obsidian staff.

1 stars273 downloadsUpdated 2mo ago0BSD

UniCalendar

A unified calendar view for Obsidian that aggregates events from Google Calendar, CalDAV servers, and ICS feeds into a single month view — with Chinese lunar calendar, solar terms, and public holiday annotations.

UniCalendar screenshot

Features

  • Unified month view — see all your calendar sources in one place, color-coded by source
  • Google Calendar sync — OAuth 2.0 PKCE flow, no server required; supports multiple calendars per account
  • CalDAV sync — connect to Nextcloud, iCloud, Fastmail, or any CalDAV-compatible server
  • ICS feed sync — subscribe to any public or private .ics URL
  • Chinese lunar calendar — lunar dates, traditional festivals (春节, 端午, 中秋…), and 24 solar terms displayed in each cell
  • Public holiday overlay — statutory holidays and adjusted workdays (补班) sourced from holiday-cn
  • Event deduplication — events shared across sources are shown once, with configurable source priority. Additional same-source deduplication removes duplicate instances when a provider returns the same occurrence more than once; if duplicates share the same source, start time, and overlapping normalized titles (exact match or one title containing the other), UniCalendar keeps the richer copy (for example the one with location, description, or meeting link metadata)
  • Auto-sync — configurable sync interval (default 30 minutes); manual sync available via command palette
  • Mobile compatible — works on iOS and Android (isDesktopOnly: false)

Installation

From Obsidian community plugins (recommended)

  1. Open Settings → Community plugins → Browse
  2. Search for UniCalendar
  3. Select Install, then Enable

Manual installation

  1. Download main.js, manifest.json, and styles.css from the latest release
  2. Copy the three files to <Vault>/.obsidian/plugins/uni-calendar/
  3. Reload Obsidian and enable the plugin in Settings → Community plugins

Configuration

Open Settings → UniCalendar to configure calendar sources.

Add a Google Calendar source

  1. Select Add source → Google Calendar
  2. Enter your Google OAuth client ID and client secret (see Google Cloud Console)
  3. Choose a Google proxy mode if your network needs help reaching Google OAuth and Calendar API endpoints
  4. Select Authorize — a browser window opens for the OAuth flow
  5. After authorization, select which calendars to include

Google proxy modes

UniCalendar supports three Google proxy modes:

  • System proxy — uses Obsidian/Electron networking. This is the default and respects the proxy behavior provided by the app/runtime.
  • No proxy — sends Google requests directly from the desktop plugin process. Use this when a system proxy interferes with Google requests.
  • Custom proxy — connects through a local or LAN HTTP proxy with host and port, for example 127.0.0.1 and 7897.

Custom proxy mode is for standard HTTP CONNECT proxies. UniCalendar opens a CONNECT tunnel to Google, upgrades it to TLS, and then sends the original Google OAuth token and Calendar API requests through that tunnel. It is not a forwarding endpoint and does not use a target= query parameter.

The legacy Google proxy address field is kept only for older saved data migration. New saves store proxyMode, proxyHost, and proxyPort, and clear the old proxyUrl value.

Add a CalDAV source

  1. Select Add source → CalDAV
  2. Enter the server URL, username, and password
  3. Select Discover calendars to list available calendars

For Feishu/Lark CalDAV performance notes and troubleshooting, see Feishu CalDAV diagnostics.

Add an ICS feed

  1. Select Add source → ICS feed
  2. Paste the ICS URL
  3. Optionally set a display name and color

Other settings

SettingDefaultDescription
Sync interval15 minHow often to auto-sync all sources
Show lunar calendarOnDisplay lunar dates and festivals in month cells
Show holidaysOnOverlay public holiday and workday annotations
Month overflow modeExpandHow to handle cells with more events than fit

Event title filters

Use Settings → UniCalendar → Event title filters to hide noisy events across all calendar sources without deleting the underlying event data.

Each rule supports two modes:

  • Hide when title exactly matches — useful for suppressing one recurring event name only
  • Hide when title contains the string — useful for suppressing classes of events by keyword

Examples:

  • Input WaytoAGI晚8点共学 with exact match hides only events whose title is exactly WaytoAGI晚8点共学
  • Input WaytoAGI with contains hides any event whose title contains WaytoAGI

Matching is case-insensitive and ignores leading/trailing or repeated whitespace.

Usage

  • Select the calendar icon in the ribbon to open the calendar view
  • Use the command palette (Ctrl/Cmd+P) and search for Open calendar
  • Navigate months with the < and > arrows in the view header
  • Select any event to see its full details

Privacy

UniCalendar operates entirely locally. Calendar credentials are stored in your vault's plugin data file (<Vault>/.obsidian/plugins/uni-calendar/data.json). No data is sent to any third-party service other than the calendar providers you explicitly configure. Holiday data is fetched from the jsdelivr CDN on first load and cached locally.

Development

UniCalendar is an Obsidian community plugin. The TypeScript entry point is main.ts, bundled by esbuild into root-level main.js, which Obsidian loads together with manifest.json and optional styles.css.

Project structure

src/
  main.ts                 # Plugin lifecycle, command/view registration
  lunar/                  # Lunar calendar, solar terms, and holiday services
  models/                 # Shared domain types
  settings/               # Settings tab and configuration UI
  store/                  # Event storage, filtering, and deduplication
  sync/                   # Google, CalDAV, and ICS sync adapters
  views/                  # Calendar view and event detail modal
tests/                    # Vitest test suites and Obsidian mocks
.planning/                # Version-controlled GSD Core plans and history

Keep src/main.ts small and place feature logic in focused modules under src/.

Project planning uses GSD Core. Its project context, requirements, roadmap, phase plans, summaries, and milestone archive are version controlled under .planning/. The local .gsd/ directory is retained only as a legacy migration source and is not used for new planning work.

Environment

Install dependencies into the project-local node_modules/ directory from the repository root. No PowerShell Profile function or external dependency directory is required:

npm install

Common commands

# Install dependencies.
npm install

# Watch mode, auto-recompile on save.
npm run dev

# Production build.
npm run build

# Run tests.
npm test

# Lint.
npm run lint

Manual testing

Copy main.js, manifest.json, and styles.css to <Vault>/.obsidian/plugins/uni-calendar/, then reload Obsidian and enable the plugin in Settings → Community plugins.

Manifest and releases

  • Keep manifest.json fields accurate, including id, name, version, minAppVersion, description, and isDesktopOnly.
  • Treat manifest.json id as stable after release.
  • When bumping a release version, update both manifest.json and versions.json.
  • GitHub release tags should exactly match the manifest version, without a leading v.
  • Attach manifest.json, main.js, and styles.css as individual release assets.

Plugin guidelines

  • Default to local/offline operation and document any network access clearly.
  • Do not add hidden telemetry, ads, remote-code execution, or custom auto-update behavior.
  • Use stable command IDs for user-facing commands.
  • Keep mobile compatibility in mind because isDesktopOnly is false.
  • Register events, DOM listeners, and intervals through Obsidian cleanup helpers so unload is safe.

License

0-BSD

For plugin developers

Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.