Calendar β
The Calendar module is GCM's central record of when things happen. It covers one-off events (a Christmas concert, a leaders' retreat), recurring weekly services, member birthdays pulled from the directory, and the meeting templates that drive every attendance roster.

Events vs meetings β
These two concepts are often confused because both show up on the calendar grid. They're stored separately and serve different jobs:
| Event | Meeting | |
|---|---|---|
| Where it lives | events table | meetings table |
| Purpose | A specific occurrence (date + time + place) | A recurring template that drives attendance (e.g. "Sunday Service") |
| Configured in | Calendar β Add event | Settings β Meetings |
| Recurrence | RRULE on the event itself | Implicit β every time you mark attendance, you pick a meeting |
| Scope | Optional org-unit filter | Required scope_level (org / branch / center / cell) |
A useful rule of thumb: if it has a published flyer, it's an event. If it's "what we do every Sunday at 10am," it's a meeting.
See Meetings & scope levels for the meeting model, Creating an event for one-off events.
What the calendar shows β
The month grid surfaces three layers on top of each other:
- Events β colour-coded dots, with hover-card preview.
- Birthdays β a cake icon, pulled live from the member directory.
- Recurring expansions β a single weekly event renders as 4 or 5 dots in a month, computed in the browser from the RRULE string.
The right-hand day panel lists everything happening on the selected date. The Upcoming tab flips to a chronological list of the next twenty events from today forward.
See Calendar views & day detail for the navigation patterns.
How recurrence works β
GCM stores recurrence using the iCalendar RRULE standard (RFC 5545). When you pick "Weekly on Mon, Wed, Fri until Dec 31" in the event form, that's saved as:
FREQ=WEEKLY;BYDAY=MO,WE,FR;UNTIL=20261231T235959ZTwo extra fields cover the gaps:
exception_datesβ a string array of dates to skip (e.g. cancel one specific Sunday).recurrence_end_dateβ a redundant end-date column for fast SQL filtering.
For backward compatibility there's also a legacy recurrence_rule text column accepting weekly / monthly / yearly. New events always write both β the RRULE is authoritative.
See Recurring patterns & RRULE for the full picker spec.
Exceptions β
The exception_dates array handles the simple case ("just skip this date"). For richer overrides β change the title for one occurrence, move start time by an hour, cancel only this date β there's an event_exceptions table:
event_exceptions(
event_id, exception_date,
is_cancelled, override_title,
override_start_time, override_end_time,
override_location
)This lets you turn a regular Sunday Service into a "Christmas Eve Service" without forking the whole recurring event. See Event exceptions.
Reminders β
Each org has one event_reminder_config row that controls when and how reminders go out. The offsets are stored as hours-before, so [24, 1] means "24 hours before and one hour before." Channels are chosen by slug β email, sms, whatsapp, push β and tracked per-occurrence in event_reminders_sent to prevent double-sending recurring events.
See Event reminders.
Scope & branches β
Events can be filtered to a single org unit (branch, center, cell) via org_unit_id. A null value means all branches see it β useful for org-wide announcements like Christmas.
The branch filter in the calendar toolbar applies a SQL OR org_unit_id IS NULL so global events stay visible while branch-specific ones are scoped. Users whose role doesn't span all branches only see the dropdown options they're assigned to.
Permissions β
| Action | Admin | Pastor | Shepherd | Member |
|---|---|---|---|---|
| View calendar | yes | yes | yes | yes |
| Create event | yes | yes | yes | no |
| Edit event | yes | yes | own org-unit | no |
| Delete event | yes | yes | own org-unit | no |
| Configure meetings | yes | yes | no | no |
| Configure reminders | yes | no | no | no |
The permission keys are events.view, events.create, events.edit, events.delete. Members can always see the calendar but can't add to it unless explicitly granted events.create.
Next steps β
- Create an event β your first one-off date.
- Meetings & scope levels β set up Sunday Service.
- Recurring patterns & RRULE β beyond simple weekly.
- Event exceptions β when one occurrence differs.
- Event reminders β automated nudges by email / SMS / WhatsApp.
- Calendar views & day detail β month grid vs upcoming list.
- Linking events to attendance β how the calendar feeds the check-in station.