iCalendar explorations
For no particular reason than an abundance of spare time and a preference not to have my personal data locked in an application silo, I took a look into building a calendar server. Without much effort, I was able to build what amounts to a demo.
Raw ingredients:
- ical.js - an iCalendar parser
- ical-generator - an iCalendar generator
- react-big-calendar a events calendar UI component.
Mix these ingredients with node.js, yarn, babel, bootstrap, express, create react app, nodemon, and concurrently and you are almost (but not quite) there.
The problem is that each of the first three components listed "speak" a different language.
-
ical.js will convert vCalendar feeds into jCal format which is pretty low level. ical.js complements this by providing two layers of object model wrappers that simplify things, but aren't suitable for transmission across the wire.
-
ical-generator will build a vCalendar feed from a custom (and straightforward) JSON grammar.
-
react-big-calendar is fairly agnostic to the input format, as long a it is simple and you can provide the name of accesors.
With this in mind, adopting the ical-generator format seemed like the path of least resistance, and the problem splits into three pieces:
-
calendar.js (and associated calendar-test.js) provides the necessary code to round trip ical-generator input into vCalendar format and back again. Along the way, I found some minor issues with ical-generator, and if the owner of that module is ameanable, I'll submit pull requests to address them. Nothing insurmountable.
-
express.js is a minimal http server which will proxy requests for external calendars (with SSL and authentication support) and transcribe the feeds into JSON.
-
App.js a simple client which will present a form requesting the URL of a calendar feed and displaying the result using react-big-calendar.
With these three pieces in place, I can fetch my calendar and have it displayed and go back to previous months. Other than an initial impression that react-big-calendar is slow (presumably I'm using it wrong somehow), I feel I have a lot to show for very little effort - a testament to the strength of the underlying building blocks.
Possible directions from here:
-
Having the events in a simplified JSON format with universal ids makes for an excellent match for a NOSQL database like MongoDB or CouchDB.
-
Serializing a collection of events from a database into the ics format would then be a piece of cake given an ical-generator, and would allow a variety of tools to immediately be able to import and subscribe to the new calendar feed.
-
Having data in a database is hardly worth it unless there is some way to update it. Existing tools use CalDav to update requests. This is "merely" an extension of HTTP, and presumably all that is needed is a handful of CRUD methods to be implemented. What can be so hard about that? Famous last words, I know, but it would be fun to find out.
-
In parallel, the web interface can be enhanced to add dialogs for adding, updating, and removing calendar entries. If the performance problem with my usage of react-big-calendar can't be identified, this component can be replaced, perhaps keeping much of the css intact.
-
The web interface can be made into a Progressive Web Application with features like launching from the desktop/home screen, offline access, notifications and more.
The full repository on GitHub.
If I'm missing something obvious, or you have an itch to scratch and would like to collaborate, let me know either on twitter or by opening an issue.