From ICS to JSON: surfacing anticipated albums

I use MusicHarbor by Marcos Tanaka to track upcoming albums from my favorite artists (typically by syncing my data with the app.) When I see something new that I want to add to my collection I throw it on a calendar creatively titled Albums.

My calendar sits over at Proton which lets you share calendars with other users or as a syncable/downloadable ics file. As another entry into a list of experiments done because they can be I decided to surface these album events on my now page[1].

To do this I installed ics-to-json-extended and created a data file:

const { AssetCache } = require('@11ty/eleventy-fetch')
const ics = require('ics-to-json-extended')
const { DateTime } = require('luxon')

module.exports = async function () {
  const URL = process.env.SECRET_FEED_ALBUM_RELEASES
  const icsToJson = ics.default
  const asset = new AssetCache('album_release_data')
  if (asset.isCacheValid('1h')) return await asset.getCachedValue()
  const icsRes = await fetch(URL)
  const icsData = await icsRes.text()
  const data = icsToJson(icsData)
  const albumReleases = data.filter((d) => DateTime.fromISO(d.startDate) >
  return albumReleases.sort((a, b) => new Date(a.startDate) - new Date(b.startDate))

We surface the url, require the ICS conversion library, cache and convert the response using Luxon's DateTime interface to compare the current time and dates in the object returned from the calendar, which look like this:

  startDate: '20180505T020000Z',
  endDate: '20180505T060000Z',
  location: 'url',
  summary: 'Artist - Album'

Rendering the output is as simple as:

{% if albumReleases.size > 0 %}
  <h2 class="m-0 text-xl flex flex-row items-center font-black leading-tight tracking-normal dark:text-gray-200 md:text-2xl mt-8 mb-4 [&>svg]:h-7 [&>svg]:w-7">
    {% tablericon "calendar" "Albums I'm looking forward to" %}
    <div class="ml-1">Albums I'm looking forward to</div>
  <ul class="list-inside list-disc pl-5 md:pl-10">
    {% for album in albumReleases %}
      <li class="mt-1.5 mb-2">
        <span class="font-bold">{{ album.startDate | readableDate }}: </span>
        <a href="https://{{album.location}}" title="{{album.summary | escape}}">
    {% endfor %}
{% endif %}

Leaving us with: Albums I'm looking forward to

  1. At this point, a dev playground. ↩︎


  • Eleventy 🎈 v2.0.1


  • Eleventy 🎈 v2.0.1
  • Bob Monsour
  • Tom
  • Nicolas (greenman)
Cory Dransfeldt
Cory Dransfeldt

I'm a software developer in Camarillo, California. I enjoy hanging out with my beautiful family and 4 rescue dogs, technology, automation, music, writing, reading and tv and movies.