No description
| src | ||
| test | ||
| .dockerignore | ||
| .gitignore | ||
| config.example.yaml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
nostr-caldav-bridge (JS)
Nostr Relay ↔ CalDAV bridge with two-way status sync for NIP-34 git issues.
Implemented Scope
- Nostr subscriptions:
- kind
1621issues - status kinds
1630-1633 - comment kind
1622
- kind
- NIP-42 relay auth support for read/write operations
- NIP-46 bunker signer support (
bunker_url) plus local key signer fallback - SQLite state store with:
- sync token tracking
- ETag/SEQUENCE conflict handling
- sync log
- CalDAV/WebDAV endpoints:
- principal collection discovery
- per-calendar collection listing
- object GET/PUT/DELETE behavior (
DELETEintentionally unsupported) - REPORT handling for
sync-collectionandcalendar-query
- Multi-principal support with per-principal credentials and visibility filters
- Automatic per-pubkey calendars (one calendar per tracked pubkey)
- Configurable filtered calendars per principal (labels/status/text/pubkeys)
- VTODO mapping for issues, labels, status, description, and nevent URL back-links
- CalDAV -> Nostr writeback on status transitions
- Unit/integration test suite via
node:test
Run
cp config.example.yaml config.yaml
npm install
npm start
Server defaults to http://localhost:5232.
Apple Reminders Setup (HTTPS via Caddy)
Apple account verification is most reliable over HTTPS on port 443.
- Point a DNS hostname (example:
caldav.example.com) to your server IP. - Update
config.yaml:caldav.host: "::"caldav.base_url: "https://caldav.example.com"
- Edit
Caddyfileand replacecaldav.example.comwith your real hostname. - Run bridge and Caddy:
npm start
caddy run --config ./Caddyfile
- In Apple Reminders CalDAV account:
- Server:
caldav.example.com - Username/password: values from
config.yaml - SSL: on (default)
- Server:
Test
npm test
CalDAV Endpoints
PROPFIND /.well-known/caldavPROPFIND /calendars/{user}/PROPFIND /calendars/{user}/{calendarId}/GET /calendars/{user}/{calendarId}/{uid}.icsPUT /calendars/{user}/{calendarId}/{uid}.icsDELETE /calendars/{user}/{calendarId}/{uid}.ics(returns405)REPORT /calendars/{user}/{calendarId}/
Signer Modes
nostr.private_key:
nsec1...- 64-char hex private key
nostr.bunker_url:
- NIP-46 bunker URL/identifier
- when set, bunker mode is used and local key mode is ignored
If neither is set, CalDAV status changes are stored locally but Nostr publish is skipped.
Docker
Build and run with Docker Compose:
docker compose up --build
The container expects /data/config.yaml (mapped from local config.yaml) and stores DB under mounted /data.