coptic-calendar
A modern web application for tracking the Coptic Orthodox Church's fasts and feasts
live at coptic-calendar.vercel.app.
1. THE PROBLEM
The Coptic Orthodox calendar is one of the oldest liturgical calendars in continuous use — a 13-month solar calendar descended from the ancient Egyptian calendar, offset from the Gregorian year by 283 or 284 years depending on the time of year. Its fasts and feasts don't map cleanly onto any existing digital calendar standard. There is no Google Calendar integration, no widely available API, and no modern web app that presents it clearly.
For Coptic Christians tracking their liturgical year — fasting periods, feast days, movable Easter-dependent observances — the options are paper printouts or apps that haven't been updated in years.
This project builds the tool that should have existed.
2. THE CALENDAR CONVERSION ENGINE
Suggested image: screenshot of the "Today" section showing both Gregorian and Coptic dates rendered side-by-side
The core technical challenge is accurate bidirectional date conversion between the Gregorian and Coptic calendar systems — accurate across the full range of 1900–2100.
The Coptic calendar operates on a fixed 13-month structure:
- 12 months of exactly 30 days each
- 1 intercalary month (Nasie) of 5 days, extended to 6 in Coptic leap years
The conversion logic implemented in client.js:
Coptic year = Gregorian year − 283 (from September 11 onward)
Coptic year = Gregorian year − 284 (before September 11)
September 11 is the Coptic New Year (1 Thout), the anchor point around which the entire offset shifts. The 12 Coptic months — Thout, Paopi, Hathor, Koiak, Toba, Amshir, Paremhat, Parmouti, Pashons, Paoni, Epip, Mesori — each map to specific Gregorian date ranges, and the conversion accounts for leap year drift across the full two-century range.
This logic runs entirely client-side in vanilla JavaScript — no external date library, no server round-trip per conversion.
3. THE EVENT DATA PIPELINE
Suggested image: screenshot of the Fasts & Feasts panel showing the color-coded event list with the search bar
Coptic liturgical events don't exist in any structured public dataset. The event data was sourced, structured, and ingested through a custom extraction pipeline.
extract-events.js is a standalone Node.js script that processes raw liturgical data into a structured JSON format consumed by the frontend. The output feeds the Express backend's API endpoints, which serve the event list to client.js on page load.
Events are categorized into three types, each with a distinct color encoding:
| Category | Color | Description |
|---|---|---|
| Fasts | Red | Major fasting periods (Apostles' Fast, Great Lent, etc.) |
| Feasts | Green | Major feast celebrations (Nativity, Epiphany, etc.) |
| Easter | Orange | Easter and movable feasts tied to the Easter computation |
The Easter category is technically the most complex — Coptic Easter is calculated using the Alexandrian method (a variant of the Julian calendar computation), meaning its Gregorian date shifts each year and cannot be hardcoded. The event pipeline handles this as a computed field rather than a static date.
4. THE FULLCALENDAR INTEGRATION
Suggested image: screenshot of the interactive 12-month FullCalendar grid with colored event indicators on dates
The interactive calendar view is built on FullCalendar v6, configured to render all 12 months simultaneously with color-coded event indicators on each date.
FullCalendar ingests the structured event data and maps each entry to its Gregorian date for rendering — since browsers operate on the Gregorian system, the calendar display layer works in Gregorian while the "Today" section and event list surface the Coptic equivalents. The two representations stay in sync through the conversion engine.
Navigation buttons allow moving between years, recomputing event positions as the Coptic-to-Gregorian mappings shift.
5. THE ARCHITECTURE
The project is intentionally minimal — three files do the entire job.
coptic-calendar/
├── server.js # Express server — serves static files + event data API
├── extract-events.js # Standalone data pipeline — raw liturgical data → structured JSON
└── public/
├── index.html # Single-page shell
├── style.css # Full responsive layout — grid, flexbox, gradients
└── client.js # All frontend logic — date conversion, FullCalendar,
# search, navigation, event rendering
Why vanilla JS over a framework? The app has no dynamic state beyond search filtering and year navigation. React or Next.js would add build tooling, hydration overhead, and framework complexity to a problem that is fundamentally: fetch data once, render it, let the user search. Vanilla JS eliminates the abstraction layer entirely.
Why Express over a static host? The event data is served via API endpoints from server.js, keeping the data separate from the presentation layer and making it straightforward to extend — adding new endpoints for year-specific computations, iCal export, or mobile API consumption without touching the frontend.
Deployment: Vercel with a vercel.json configuration that routes all requests through the Express server, enabling the API endpoints to function in a serverless environment.
6. UI DETAILS
Suggested image: full-width screenshot of the complete app layout showing all three panels together
The layout is a three-panel design:
- Today section — current Gregorian date, computed Coptic date, and any events occurring today
- 12-month FullCalendar grid — color-coded feast and fast indicators on each date
- Fasts & Feasts panel — full searchable event list with real-time filtering as the user types, case-insensitive
The event list includes a gradient fade at the bottom edge — a CSS linear-gradient mask over the scroll container that signals more content below without a hard cutoff. Small detail; meaningful polish.
Responsive breakpoints adapt the three-panel layout to single-column on mobile, ensuring the calendar grid and event list remain usable at phone width.
WHY IT EXISTS
The Coptic calendar is 6,000 years old. It predates the Gregorian calendar by millennia, and the community that uses it deserves a tool built with the same care as any mainstream calendar app.
This project is personal. It is also precise — the conversion engine is accurate across two centuries, the event data is complete, and the interface asks nothing of the user beyond opening a browser.
Sometimes the right project is simply: build the thing that should already exist.