Calendarkit Pro V2
Features

Recurring Events

Define events that repeat daily, weekly, monthly, or yearly with optional count and until rules.

Recurring Events

CalendarKit Pro supports recurring events via the recurrence field on a CalendarEvent. The scheduler automatically expands recurring events into individual occurrences for the visible date range.

Recurrence model

recurrence?: {
  freq:       'DAILY' | 'WEEKLY' | 'MONTHLY' | 'YEARLY';
  interval?:  number;    // repeat every N units (default: 1)
  count?:     number;    // stop after N occurrences
  until?:     Date;      // stop on this date (inclusive)
  byweekday?: number[];  // 0=Monday … 6=Sunday
}

count and until are mutually exclusive. If both are set, count takes precedence.

Examples

Every day

const dailyEvent: CalendarEvent = {
  id: 'daily',
  title: 'Morning Standup',
  start: new Date('2026-07-21T09:00:00'),
  end:   new Date('2026-07-21T09:30:00'),
  recurrence: { freq: 'DAILY' },
};

Every 2 weeks, on Monday and Wednesday, for 8 occurrences

const biweekly: CalendarEvent = {
  id: 'biweekly',
  title: 'Team Sync',
  start: new Date('2026-07-21T10:00:00'),
  end:   new Date('2026-07-21T11:00:00'),
  recurrence: {
    freq: 'WEEKLY',
    interval: 2,
    byweekday: [0, 2], // 0=Monday, 2=Wednesday
    count: 8,
  },
};

Every month until end of year

const monthly: CalendarEvent = {
  id: 'monthly',
  title: 'Monthly All-Hands',
  start: new Date('2026-07-07T14:00:00'),
  end:   new Date('2026-07-07T15:00:00'),
  recurrence: {
    freq: 'MONTHLY',
    until: new Date('2026-12-31'),
  },
};

Every year (anniversary)

const anniversary: CalendarEvent = {
  id: 'anniversary',
  title: 'Company Anniversary 🎉',
  start: new Date('2026-03-15'),
  end:   new Date('2026-03-16'),
  allDay: true,
  recurrence: { freq: 'YEARLY' },
};

Weekly gym — no end

const gym: CalendarEvent = {
  id: 'gym',
  title: 'Gym',
  start: new Date('2026-07-21T18:00:00'),
  end:   new Date('2026-07-21T19:00:00'),
  color: '#10b981',
  recurrence: {
    freq: 'WEEKLY',
    interval: 1,
    byweekday: [1, 3, 5], // Tuesday, Thursday, Saturday
  },
};

byweekday reference

ValueDay
0Monday
1Tuesday
2Wednesday
3Thursday
4Friday
5Saturday
6Sunday

Full example

'use client';

import { useState } from 'react';
import { ProScheduler } from 'calendarkit-prov2';
import type { CalendarEvent } from 'calendarkit-prov2';

const recurringEvents: CalendarEvent[] = [
  {
    id: 'standup',
    title: '☕ Daily Standup',
    start: new Date('2026-07-21T09:00:00'),
    end:   new Date('2026-07-21T09:15:00'),
    color: '#3b82f6',
    recurrence: { freq: 'DAILY' },
  },
  {
    id: 'gym',
    title: '🏋️ Gym',
    start: new Date('2026-07-21T18:00:00'),
    end:   new Date('2026-07-21T19:00:00'),
    color: '#10b981',
    recurrence: {
      freq: 'WEEKLY',
      byweekday: [1, 3, 5], // Tue, Thu, Sat
    },
  },
  {
    id: 'retro',
    title: 'Sprint Retrospective',
    start: new Date('2026-07-24T15:00:00'),
    end:   new Date('2026-07-24T16:00:00'),
    color: '#8b5cf6',
    recurrence: {
      freq: 'WEEKLY',
      interval: 2, // every 2 weeks (biweekly)
    },
  },
  {
    id: 'monthly',
    title: '📊 Monthly Review',
    start: new Date('2026-07-07T14:00:00'),
    end:   new Date('2026-07-07T15:30:00'),
    color: '#f59e0b',
    recurrence: {
      freq: 'MONTHLY',
      count: 12, // 12 months
    },
  },
];

export default function RecurringExample() {
  const [events, setEvents] = useState<CalendarEvent[]>(recurringEvents);

  return (
    <div className="h-[700px] border rounded-xl overflow-hidden">
      <ProScheduler
        view="week"
        events={events}
        date={new Date()}
        onEventCreate={(e) =>
          setEvents((prev) => [...prev, { ...e, id: crypto.randomUUID() } as CalendarEvent])
        }
        onEventUpdate={(updated) =>
          setEvents((prev) => prev.map((e) => (e.id === updated.id ? updated : e)))
        }
        onEventDelete={(id) =>
          setEvents((prev) => prev.filter((e) => e.id !== id))
        }
      />
    </div>
  );
}

How recurrence expansion works

When the calendar renders, it looks at all events with a recurrence field and generates virtual occurrence instances for the visible range. These instances share the same base id (e.g. 'standup') and are rendered identically to regular events. Modifying an occurrence in the modal edits the base event (updating all future occurrences).

On this page