A fast, minimal, customizable, keyboard-first calendar web app. Kalkee provides remappable shortcuts, quick and intuitive navigation, as well as Google Calendar or CalDAV sync.
- Intuitive only keyboard navigation across week, month, and multi-day views
- Dependency-free browser client
- Remappable actions in a dedicated shortcut editor
- Two-way Google Calendar and CalDAV event sync
- Customizable appearance settings and preset themes
- Docker and native Node.js deployment
Requirement: Node.js 20 or newer. Provider credentials are only needed for synchronization.
cp .env.example .env
npm install
npm startOpen http://localhost:3000. Without a connected provider, Kalkee starts in local preview mode with sample events.
Generate a session-encryption secret if you intend to use CalDAV or want a key independent of the Google client secret:
openssl rand -hex 32Save it as CALENDAR_SESSION_SECRET in .env. Without an encryption secret, CalDAV still works, but its login only lasts until the server restarts.
To connect Google Calendar:
- Create a Google OAuth web client and enable the Google Calendar API.
- Add
http://localhost:3000as an authorized redirect URI. - Set
GOOGLE_CLIENT_IDandGOOGLE_CLIENT_SECRETin.env. - Restart Kalkee and select Google.
For another hostname or port, set GOOGLE_REDIRECT_URI and register that exact HTTPS URI in Google Cloud. The scheme, host, port, path, and trailing slash must match.
Select CalDAV and enter a server or calendar URL, your username, and a password or app password. Kalkee discovers the available event calendars and lets you choose which one to connect. For example, a Nextcloud collection commonly looks like:
https://cloud.example.com/remote.php/dav/calendars/username/calendar-name/
Kalkee currently uses CalDAV Basic authentication, which is intended for HTTPS and commonly paired with an app-specific password. Plain HTTP is accepted only for localhost unless CALDAV_ALLOW_HTTP=1 is explicitly set for development.
cp .env.example .env
docker compose up --build -dThe app is available at http://localhost:3000. Encrypted calendar sessions are stored in the kalkee-data Docker volume rather than the container filesystem.
To publish on another port, set KALKEE_PORT. Also set GOOGLE_REDIRECT_URI to the public address and register it with Google:
KALKEE_PORT=8080 docker compose up --build -dUseful commands:
docker compose logs -f kalkee
docker compose restart kalkee
docker compose downThe defaults are:
| Action | Key |
|---|---|
| Move through days and times | H / J / K / L |
| Confirm or open a selection | Enter |
| New event | N |
| Mark an event range | M |
| Move an event | G |
| Resize event start / end | S / E |
| Delete selected event | Delete |
| Go to today | T |
| Previous / next period | [ / ] |
| Week / month / days view | W / V / D |
| Search events | / |
| Settings | , |
Every listed binding can be changed under Settings → Shortcuts.
Calendar events remain with the connected provider. OAuth tokens and CalDAV credentials stay on the Node.js server; the browser receives an HTTP-only session cookie. When CALENDAR_SESSION_SECRET (or, for Google-only setups, GOOGLE_CLIENT_SECRET) is available, sessions are encrypted with AES-256-GCM and persisted in the ignored .calendar-sessions.enc file or /data/sessions.enc in Docker.
Calendar ranges are cached in browser memory and adjacent periods are prefetched. Local preview edits remain in the browser session and reset on reload.
npm run dev
npm run check
npm run test:e2eThe included kalkee.service is an example systemd user unit for this checkout path. Adjust its paths when installing elsewhere.
See SECURITY.md for reporting vulnerabilities.
MIT



