Skip to content

calendaryjs-plugin-ics

Turn the events calendaryjs generates into a standard .ics VCALENDAR that Apple Calendar, Google Calendar, Outlook and anything else can subscribe to.

Terminal window
npm i calendaryjs calendaryjs-plugin-ics
import { calendary } from "calendaryjs";
import { every, date } from "calendaryjs/builder";
import { toICS } from "calendaryjs-plugin-ics";
const cal = calendary();
cal.addGroup({
id: "holidays",
events: [
every("year").on(date(1, 1)).title("New Year"),
every("year").on(date(12, 25)).title("Christmas"),
],
});
const events = cal.getEventsInRange("2025-01-01", "2025-12-31");
const ics = toICS(events, { calendarName: "Holidays" });
// → write `ics` to a .ics file, or serve it from an endpoint

Events arrive already expanded — the core has applied recurrence, the startDate / endDate validity window, exceptions and overrideDates before you call toICS(). So the exporter emits one VEVENT per occurrence and never needs an RRULE. Non-Gregorian recurrences (lunar, hijri, formula) therefore export correctly, because every occurrence is just a concrete date by the time it reaches ICS.

calendaryjsICS
date + startTime / endTimeDTSTART / DTEND (floating local time)
date (all-day / no time)DTSTART;VALUE=DATE + exclusive DTEND
duration (minutes)DURATION (when endTime is absent)
titleSUMMARY
description / location / urlDESCRIPTION / LOCATION / URL
categories / statusCATEGORIES / STATUS
priority (z-index)PRIORITY (inverted, 1 = highest)
color / iconCOLOR / IMAGE (RFC 7986)
reminders[] (minutes before)VALARM with TRIGGER:-PTnM
source / groupId / id + datea stable, unique UID

Timed events export as floating local time (no Z, no TZID) — the core stays timezone-neutral, so occurrences render in the viewer’s local zone. Reminder and duration units are minutes.

toICS(events, {
prodId, // PRODID. Default "-//calendaryjs//calendaryjs-plugin-ics//EN"
calendarName, // X-WR-CALNAME — the calendar's display name
method, // METHOD, e.g. "PUBLISH"
dtstamp, // DTSTAMP for every event (pass a fixed Date for stable output)
priorityMap, // override priority → ICS PRIORITY (return 0 to omit)
});

eventToVEvent(event, options?) serializes a single occurrence to one VEVENT block (no VCALENDAR wrapper).

  • RRULE compaction for Gregorian-expressible recurrences (with EXDATE / RECURRENCE-ID for exceptions).
  • ICS import (.ics → event configs).