Authoring a plugin
A plugin teaches calendaryjs a new event type (a recurrence rule), and can optionally enrich each day with extra data or register named formulas. Anyone can publish one — official and community plugins use the exact same shape.
1. Start from the template
Section titled “1. Start from the template”The fastest path is the official template:
# copy templates/calendaryjs-plugin out of the calendaryjs repo, then:npm installnpm testOr scaffold by hand: a plugin is just a package that depends on calendaryjs as a
peer dependency and exports a factory returning a CalendaryPlugin.
2. The plugin shape
Section titled “2. The plugin shape”import type { CalendaryPlugin } from "calendaryjs";
export function myPlugin(): CalendaryPlugin { return { name: "calendaryjs-plugin-my-thing", version: "0.1.0", eventTypes: { "my-thing": { // narrow the unknown event to your shape validate(event): boolean { const e = event as Record<string, unknown>; return e.type === "my-thing" && typeof e.id === "string"; }, // return the Gregorian date(s) this event falls on in `year` generate(event, year): Date[] { const e = event as { month: number; day: number }; return [new Date(year, e.month - 1, e.day)]; }, }, }, };}Use it:
import { calendary } from "calendaryjs";import { myPlugin } from "calendaryjs-plugin-my-thing";
const cal = calendary().use(myPlugin());cal.addGroup({ id: "g", events: [{ type: "my-thing", id: "x", month: 6, day: 1 }],});3. Optional: enrich each day
Section titled “3. Optional: enrich each day”To attach data to every CalendarDay (like a lunar or Hijri date), register a day
enricher in install() and augment the CalendarDay type:
declare module "calendaryjs" { interface CalendarDay { myInfo?: { foo: string }; }}
// inside the plugin:install(calendary) { calendary.registerDayEnricher({ name: "my-thing", priority: 10, enrich: (day) => ({ ...day, myInfo: { foo: "bar" } }), });}4. Name it so it’s discoverable
Section titled “4. Name it so it’s discoverable”This is what makes your plugin show up in the plugins directory:
- Package name:
calendaryjs-plugin-<name>(e.g.calendaryjs-plugin-fiscal-year). - Keyword: add
"calendaryjs-plugin"topackage.jsonkeywords. The directory crawls npm for this keyword — no registration step. - Peer dependency:
"calendaryjs": ">=0.1.0"(your plugin works with whatever version the user already installed).
{ "name": "calendaryjs-plugin-fiscal-year", "keywords": ["calendaryjs-plugin", "calendar", "fiscal"], "peerDependencies": { "calendaryjs": ">=0.1.0" },}5. Publish
Section titled “5. Publish”npm publishThat’s it — no scope, no custom CLI, no registry to sign up for. Within a day the
plugins directory picks it up via the calendaryjs-plugin keyword, alongside its
npm download count.
See Plugins for how plugins are loaded and discovered.