Skip to content

Recurring events

Author with the fluent builder (recommended) — it compiles to the plain config the engine stores and exports.

import { calendary } from "calendaryjs";
import { every, weekly, monthly, date, nth } from "calendaryjs/builder";
const cal = calendary();
cal.add(
every("year").on(date(12, 25)).title("Christmas"), // every Dec 25
weekly("monday").title("Standup"), // every Monday
every(2, "weeks").on("tuesday").title("Biweekly sync"), // every other Tuesday
monthly(-1).title("Rent"), // last day of every month
every("month").on(nth(1, "monday")).title("Retro"), // 1st Monday of the month
every("month").on(nth(-1, "friday")).title("Payday"), // last Friday of the month
every(3, "days").title("Water the plants"), // every 3 days
);
cal.getEventsInRange("2026-01-01", "2026-01-31").map(e => `${e.date} · ${e.title}`);

Recurrences are infinite by default — bound them three ways:

// After N occurrences (like RRULE COUNT) — needs a start to count from:
cal.add(weekly("tuesday").starting("2026-09-01").times(10).title("Course")); // 10 classes
// Between two dates (inclusive):
cal.add(every("week").on("wednesday").between("2026-06-01", "2026-08-31").title("Summer class"));
// Every Nth year, phased from a start year:
cal.add(every(4, "years").on(date(6, 1)).starting(2024).title("Reunion")); // 2024, 2028, …

Prefer plain objects? Every builder is just sugar for a config — the same shape a .cdy stores. See Event types for every field and Building events for the full grammar.