---
title: CalendarChanger
subtitle: Smart ICS Proxy for Structured and Customizable Calendars
showOnCv: true
type: Personal
abstract: A self-hosted ICS proxy that restructures and enriches iCalendar feeds to use proper field semantics for cleaner and more useful subscriptions.

images:
  - src: cover
    srcDark: cover-dark
    filetype: .webp
  - src: calendar
    srcDark: calendar-dark
    filetype: .webp

pdfFiles: []

quickLinks:
  - kind: github
    url: https://github.com/wtb04/calendarchanger
  - kind: demo
    url: https://calendarchanger.w-tb.nl

keywords: []
supervisors: []

keyFeatures:
  - "ICS Proxy: Rewrites feeds to use correct iCalendar fields instead of description text"
  - "Smart Grouping: Creates separate subscriptions for lectures exams and practicals"
  - "Web Interface: Edit or hide events without altering the source feed"
  - "Event Hashing: Restores edited events automatically when the source changes"
  - "Location Integration: Adds Apple Maps and Mazemap links for classroom details"
  - "RFC 2445 Compliance: Outputs standards-compliant ICS data"
  - "Continuous Sync: Periodically refreshes from the source feed"
  - "Dockerized Deployment: Automated through Ansible for continuous delivery"

tags:
  - Backend
  - Automation
  - ASP.Net Core
  - Docker
---

CalendarChanger is a self-hosted <a href='https://www.rfc-editor.org/rfc/rfc2445' target='_blank'>iCalendar (ICS)</a> proxy that fixes and enriches exported calendar feeds. The project began when the University of Twente adopted <a href='https://www.timeedit.net/nl_utwente' target='_blank'>TimeEdit</a> in 2024. While TimeEdit provided technically valid ICS files, it stored all details inside the description field instead of using the correct iCalendar fields such as LOCATION and ATTENDEE. This made the data unreadable in most calendar apps. CalendarChanger acts as a middle layer between TimeEdit and the calendar client, extracting and reformatting event data to fully leverage standard ICS semantics. It cleans titles, assigns teachers as attendees, and separates lectures, exams, and practicals into individual feeds so users can color-code them in their calendar. 

It also adds richer context by inserting Apple Maps locations and linking building names to a custom Mazemap redirect endpoint that resolves rooms to <a href='https://use.mazemap.com/' target='_blank'>Mazemap</a> locations. The system runs continuously, fetching updates from the original feed and serving always up-to-date subscriptions. 

The web interface lets users hide or modify events such as cancelled classes or changed times even though the source is read-only. Each event is hashed by its contents so when TimeEdit updates an event it reverts to its original form ensuring consistency. The backend is built with ASP.NET Core and Razor Pages, containerized with Docker, and deployed automatically with Ansible to a private cloud server.