Case · Backend · Python

ical-forge: iCalendar (RFC 5545), RRULE and subscription

An iCalendar service in Python (FastAPI + SQLite, no third-party calendar libraries). It builds a valid .ics (line folding, escaping, VTIMEZONE from zoneinfo), validates a foreign file with line numbers, expands recurring events by RRULE and publishes subscription feeds by link with ETag and 304 responses.

  • Python
  • FastAPI
  • uvicorn
  • SQLite
  • RFC 5545
  • ETag
  • hypothesis
  • mypy --strict
  • ruff
  • Docker
  • GitHub Actions

01 · How it looks

Screenshots

Screenshot of the project "ical-forge: iCalendar (RFC 5545), RRULE and subscription" at 1280 pixels wide
Desktop, 1280 px
Screenshot of the project "ical-forge: iCalendar (RFC 5545), RRULE and subscription" on a phone screen, 390 pixels wide
Phone, 390 px

02 · About

What it is and why

An iCalendar service in Python (FastAPI + SQLite, no third-party calendar libraries). It builds a valid .ics (line folding, escaping, VTIMEZONE from zoneinfo), validates a foreign file with line numbers, expands recurring events by RRULE and publishes subscription feeds by link with ETag and 304 responses.

Limitations

SECONDLY, MINUTELY, HOURLY and some of BYWEEKNO, BYYEARDAY, BYHOUR, BYMINUTE, BYSECOND are not expanded: the syntax is accepted, expansion returns an error.

Events with a non-IANA TZID (for example Windows names) are validated but not expanded.

This is a demo store without accounts; the rate limit lives in process memory.

The project runs on a small VPS with demo data: no redundancy or backups.

What is inside

  • 28 recurrence examples from RFC 5545 §3.8.5.3 are checked against date lists (BYSETPOS, "second-to-last Monday", Friday the 13th with EXDATE)
  • 119 tests; hypothesis: an event → .ics → event round trip over arbitrary Unicode, unfold(fold(x)) == x, lines of at most 75 octets
  • POST /api/expand of 500 occurrences in 0.2 s; a feed at about 640 requests per second, p95 45 ms
  • The edit key is stored only as a SHA-256, compared in constant time

03 · How to run

Run it locally

git clone <repository on request> ical-forge
cd ical-forge
python -m app

04 · Code

The repository is private

The source is in a private repository. Message me on Telegram and I will open access.

Request the code