elmcity project status


Somebody wrote today noticing this space was silent and wondering if the project were also. Nope, it’s alive and well, I just haven’t been documenting it here.

The best summary of the current state of play is a screencast I made today.


The URL pattern http://elmcity.cloudapp.net/ID — so, for example, http://elmcity.cloudapp.net/BlacksburgVA — now yields an About this Hub page into which I am organizing all the documentation.

Thanks to David Moore for suggesting this.


The feed editor now has two more fields:

1. approved. Default: yes. Set to no if you want to keep track of a feed but you’re not yet ready to publish it.

2. comments. A place to narrate the status of a prospective or approved feed.

Thanks to David Moore for suggesting this.


Curators can now map user-contributed tags to the curated hub taxonomy. For example, the Harris County Public Library in Houston uses a CMS that supports tags. Here are some they’ve used:

adult program
all ages
baby time
book discussion
book sale

By default these show up in the tag picker in squigglies to indicated they are user-contributed and not curator-assigned:

{adult program}
{all ages}
{baby time}
{book discussion}
{book sale}

As curator I would like events tagged {book discussion} and {book sale} to show up in the hub taxonomy’s books category.

Here is the existing record in the hub’s registry:

“url” : “http://hcpl.net”,
“feedurl” : “https://host4.evanced.info/harris/evanced/eventsxml.asp?dm=ical&ag=&et=&lib=ALL&nd=90&feedtitle=Multiple+Branch%3CBR%3ESchedule+of+Events&LangType=0”,
“source” : “Harris County Public Libraries”,
“category” : “library,hcpl”

I add a new element, catmap:

“url” : “http://hcpl.net”,
“feedurl” : “https://host4.evanced.info/harris/evanced/eventsxml.asp?dm=ical&ag=&et=&lib=ALL&nd=90&feedtitle=Multiple+Branch%3CBR%3ESchedule+of+Events&LangType=0”,
“source” : “Harris County Public Libraries”,
“category” : “library,hcpl”,
“catmap” : “http://jonudell.net/elmcity/catmap-houston-harris-library.json”

The URL points to:

“baby time” : “children”,
“bilingual” : “language”,
“book discussion” : “books”,
“book sale” : “books”,
“children’s program” : “children”,
“computer class” : “technology,classes”,
“esl/literacy” : “language,education”,
“family program” : “family”,
“gulf coast reads – book discussion” : “books”,
“gulf coast reads” : “books”,
“movie” : “film”,
“story time” : “books”,
“toddler time” : “children”,
“tweens” : “children”,
“young adult/teen program” : “children”

Now events with per-event tags from the left column show up in the categories defined by the right column.

It’s also possible to include a catmap directly, like so:

“url” : “http://hcpl.net”,
“feedurl” : “https://host4.evanced.info/harris/evanced/eventsxml.asp?dm=ical&ag=&et=&lib=ALL&nd=90&feedtitle=Multiple+Branch%3CBR%3ESchedule+of+Events&LangType=0”,
“source” : “Harris County Public Libraries”,
“category” : “library,hcpl”,
“catmap” : ” { ‘book sale’:’books’, ‘book discussion’:’books’, ‘movie’:’film’ } ”

Because this feature is advanced and rarely needed, the catmap is not (yet) available in the regular feed editing view. It is available in the Edit All Feeds view.

Note that (for now) the original user-contributed categories are preserved in squigglies. So, for example:

Mon 03:00 PM Popcorn and a Movie Harris County Public Libraries film, hcpl, library, {movie} … +


The Facebook helper (at URL helpers) now accepts the URL of either a Facebook fan page or a Facebook group, and produces an iCal URL for (future) events in either of those places. Formerly only fan pages could have calendars, now (thanks to Burt Lum for pointing this out) group pages can too.


The URL helpers page now includes a bookmarklet that extracts the Google Calendar iCal URL from a page that embeds a Google Calendar widget. Many thanks to David Moore for reminding me to do that.


The default HTML rendering now adds an ellipsis (…) to items for which the iCalendar DESCRIPTION is non-empty, clicking the ellipsis expands to show the description inline.


The scheduler now works in a different and more flexible way. Formerly there were two schedules: one for geographic hubs and another for topical hubs. A geographic hub is (typically) a mixture of non-iCal sources (Eventful, Upcoming, EventBrite, Meetup) and iCal sources. A topical hub only has iCal sources.

Formerly the geographic hubs were aggregated less frequently than topical hubs in order not to overtax the Eventful/Upcoming/etc APIs. But that meant that iCal sources for those hubs were aggregated less frequently than for topical hubs, which didn’t make sense.

Now all non-iCal tasks happen on one schedule, currently every 8 hours, and all iCal tasks happen on another schedule, currently every 2 hours.

(There’s actually a third schedule for regional hubs like MonadnockNH, which are virtual containers for sets of hubs.)

This means that if your hub is geographical and uses both non-iCal and iCal sources, then over the course of 8 hours it will update 5 times instead of 1 as formerly — that is, once for the non-iCal sources, and 4 times for the iCal sources.


The Add to Calendar feature (behind the + in event listings) now includes Add to Facebook. This is so individuals can pluck events of interest off the calendar and socialize them with friends.


I’ve just made a big change to the mechanism that coalesces events. Formerly it required an exact match for both date/time and title. I’ve been wanting to do a fuzzier match but hadn’t figured out a good approach, now I think I have. You won’t notice the effect unless you’re running a big hub with substantial overlap among various sources, but for hubs in that category — Boston, Seattle — it’s making a huge difference.


There’s now an iCalendar filter for the LOCATION property of feeds. The URL helpers page shows how to use it to distinguish between home games and away games in a sports feed. (Thanks to Clif Hirtle whose socialhartford hub surfaced the need for this filter.)


Each event rendered in the HTML view now provides an Add to Calendar link that moves the information to a personal calendar — currently two web-style apps (Google Calendar, Hotmail Calendar), plus all desktop-style apps that are iCalendar-aware (e.g. Outlook, Apple iCal). Additional web-style apps can easily be added as needed.


There’s now a mechanism for bundling a set of location hubs to create a regional hub. For example, MonadnockNH bundles the following hubs: elmcity (Keene), Jaffrey, Fitzwilliam, Dublin, Hancock, Gilsum, Harrisville, Nelson, Marlborough, Peterborough, and for good measure Brattleboro Vermont.

Each of the bundles hubs exists and is curated independently. The regional hub is just a virtual container for them.


There’s now a page of URL helpers — http://elmcity.cloudapp.net/url_helpers — that help curators build various kinds of special-case iCalendar URLs. Currently for: Facebook, iCalendar filtering, RSS+xCal, CSV, and HighSchoolSports.Net.


HighSchoolSports.net is a very fruitful source of iCalendar feeds, not only for high schools but also for middle schools in some places. (Only US places, I guess.) If you use the Synch feature on the site it appears that you can only get team calendars in batches of 5 which is inconvenient. But there’s no real limitation. So if you want to take feeds individually or in groups (e.g., all basketball, including boys/girls and varsity/jv), you can. But if you want them all in a batch, which I’ve decided I do for now, here’s a way to form the all-in-one-feed URL:


SCHOOL is a name like Cleveland-High-School-Seattle-WA which you’ll find by searching the site for your town.

TZ is one of ET, CT, MT, PT, AT (Alaska time), HT (Hawaii time)

So, for example, this:


Yields this:


It’s long, but you can plug it into the feed editor and it’ll work.


The feed editor now includes a tag cloud to help curators visualize the tag namespace. It’s a first step towards enabling curators to bulk-edit the tag namespace — i.e. rename tags, delete tags, as was possible in Delicious.


Views are now available in ICS format as well as XML/RSS/JSON.



The HTML view now coalesces events with the same title and start. A coalesced event merges the source names, urls, and tags of its sources. Here’s an example from Berkeley. The event comes from Eventful, Upcoming, and also the Berkeleyside calendar:

Wed 05:00 PM Gather Restaurant in Berkeley Hosts Lindencroft Farm Harvest Dinner on October 26 [ 1 ,  2 ,  3 ] berkeleyside, eventful, upcoming


Event listings on Facebook pages are now available. For example, here is the Facebook page for the Blind Pig in Ann Arbor:


To form an iCalendar URL from this, capture the id of the page: 57679984081

Then use this template:


Swap in the page id for fb_id, and the hub id for elmcity_id. So if the page id is 57679984081 and the hub id is a2cal then the iCalendar URL is:


You can test this by using the iCalendar validator at icalvalid.cloudapp.net. Go there, pop in your iCalendar URL, and check to see that events are found and that the text of the feed is as expected.

To search for Facebook pages, try this (swapping in your location):


(Thanks to Clif Hirtle, curator for the socialhartford hub, for suggesting this!)


Two more authentications: Windows Live and Google.


Facebook authentication is now available too. New curators will choose between Facebook and Twitter. Existing curators can ask to be converted to either of these methods.


Curators can now sign in using the Twitter accounts associated with their hubs in order to directly edit hub configurations and add/edit/delete feeds.

If you have an existing hub the Delicious mechanism will continue to work, there is no need to change, but if you want to use the new integrated hub and feed editor just notify me (jonu@microsoft.com) and I’ll switch you over. If you haven’t already linked a Twitter account to your elmcity hub, let me know which one you’d like to use.


Facebook events can now be syndicated, as well as searched for. Details.


With build 986 the HTML rendering embeds RDFa markup that will enable events to be recognized by search engines.

It also includes latitude/longitude coordinates in the XML and JSON feeds.

(See this blog post for the rationale.)


Build 867 adds parsing for RSS feeds that include structured calendar data in the xCal namespace. Some example URLs that produces this type of feed, from sites that use zevents.com:



To activate the xCal -> iCalendar translator for feeds of this type, bookmark them with the usual trio of tags:

trusted ics feed

and then also add this key/value pair:


Note that the second example uses cat=3 which, in this context, means Business/Tech. It appears that for zevents.com-based sites, an elmcity curator can produce multiple tagged feeds by naming the categories. So for example, if you bookmarked the above pressdemocrat feed you could tag it with category=business and do likewise for all the other categories.


Current build is 856. Many internal improvements since last update, but the key user-visible change is:


This helps new curators verify that a delicious account is properly set up to control an elmcity hub. It’s also a useful way for established curators to review settings in delicious, the permanent record of those settings stored in Azure, and the current set of trusted feeds.


As of build 777, the source code is released and I’ve begun a series of articles about the development of the project.

Among other recent activities, I’ve been reviewing how curators are including the default HTML rendering in their sites. Sourcing the HTML into an iframe is a popular approach, as seen for example on berkeleyside. In that situation you’d probably like to suppress the calendar’s header image, since the enclosing page already has one. This was formerly only possible by redirecting to an alternate template, but a lighter solution is now available: use header_image=no in your metadata.

Another strategy for sourcing events into a web page can be seen at InMenlo, where the combined ICS feed from the elmcity aggregator is routed back through Google Calendar, and the results sourced into the page. I’ve noticed a lot of duplicate events in that presentation, and I theorize that it’s happening because the IDs I’ve been generating were unique but not stable on a per-event basis across aggregator runs. So I’ve switched to a strategy that will produce stable unique IDs and will watch what happens. Even if I’m right, it may take a while for the duplicates to scroll off the event horizon.


Given the hiatus since 607, build 659 clearly includes a lot. Much is internal, as I prepare to release the code as open source. But at least these things are visible:

1. New http://elmcity.cloudapp.net homepage, with these improvements: a) /services/ID is now, instead of 404, a helpful document that names and explains all the subsidiary links b) replacement of the dropdown list with a link to a). (/via Rob Goodspeed)

2. tags now link to category views For example, if an event is in the category music, then the default rendering links music to an url like http://elmcity.cloudapp.net/services/elmcity?view=music (/via Bill Rawlinson)

3. Facebook is now an event source. See: http://blog.jonudell.net/2010/05/07/facebook-is-now-an-elmcity-event-source/.


Build 607 introduces the new iCalendar validator which Doug Day, who is also the author of the iCalendar component I am using, has graciously provided.

On the stats page now — for example, http://elmcity.cloudapp.net/services/prescottaz/stats — the column formerly labeled valid? is now labeled score. The score is a number from 0 to 100, which nicely represents the idea that the validity of a calendar feed is, practically speaking, not a binary yes/no but rather a point along a continuum.

If you click a value in that column, you’ll invoke the validator for the corresponding feed.

Alternatively, if you want to check the validity of a feed, you can do it directly at http://icalvalid.cloudapp.net.


Build 605 includes few if any curator-visible changes, but much internal improvement. Especially in the areas of caching and service self-monitoring.


Build 556 adds a major new source of events for all geographic hubs: Eventbrite. It works the same way as the Eventful and Upcoming sources, and happens automatically, curatators don’t have to do anything extra or different.


Build 540 adds two new administrative features for curators: log viewing, and metadata viewing.

1: Log viewing

The URL pattern for the log viewer is:


So, for example, here’s the last 60 minutes of activity for the Keene hub:


If minutes is more than 500, it’ll become 500.

2: Metadata viewing

The URL pattern for the metadata viewer is:


You wouldn’t normally need this. But if you want to make sure that the metadata you’ve specified in Delicious has been accurately and completely transmitted to the elmcity service, you can use this URL to check. It retrieves the mirror of your Delicious metadata that’s stored in an Azure table, plus some computed or looked-up values that aren’t in Delicious:

  • events
  • population
  • feed_count

If you have made a change to your Delicious metadata, you might want to send a Twitter start message to the service in order to start a new cycle. You can watch its progress in your log viewer. Look for entries like these:

 8:53:45 PM info 5872,RD00155D301CF7: Scheduler.StartTaskForId: eLearningEvents 
 8:53:45 PM info 5872,RD00155D301CF7: processing hub: eLearningEvents 
 8:54:03 PM info 5872,RD00155D301CF7: DoIcal: eLearningEvents 

Once you see DoIcal, your metadata should be synched to Azure. You can check your metadata URL to verify.


Build 538 adds the ability for curators to short-circuit the normal cycle and start a new one. You do this by sending a Twitter direct message to @elmcity_azure. If the message says:


then your cycle will restart within 5 minutes.


Major changes in build 516:

Improved calendar widget in HTML views
The new version, based on the JQuery datepicker, stays in a fixed position as you scroll, and ajusts itself to the closest displayed date.

Hubs using the default template will see this new behavior. Hubs that have altered the default template may want to resynch with it.

RSS views
The following flavors work:

1. http://elmcity.cloudapp.net/services/elmcity/rss

2. http://elmcity.cloudapp.net/services/elmcity/rss?view=government

3. http://elmcity.cloudapp.net/services/elmcity/rss?count=30

4. http://elmcity.cloudapp.net/services/elmcity/rss?view=music&count=10

This flavor should be especially useful for systems, like WordPress.com, that will not display dynamic content but will display RSS feeds. You can see example 4 in action on my blog (scroll down to “Upcoming music in Keene”).


Build 452 adds new standard views for tag summaries (as HTML and as JSON). So for example:






Build 441 includes WHERE and WHAT hubs on the homepage, and streamlines the display of all associated links.


Build 430 converts internally to UTC times. This mainly benefits topical hubs, since their events cross timezones. The data feeds — XML, JSON, iCalendar — are now all expressed in terms of UTC.

For geographical hubs, the data feeds are also expressed in terms of UTC. However, the HTML view converts to local time as defined by the tz= metadata slot. Since geographical hubs are only using the HTML view, and none (I think) are using the data feeds, there should be no observable change.


Build 420 adds a new axis of aggregation: topic rather than geographic location.

The mechanism is similar. Basically just what= instead of where= in the delicious metadata.

The first two examples are:



In these cases, there is no aggregation from Eventful and Upcoming, because there is no location. So it’s purely aggregation of a list of iCalendar feeds, which are handled in the usual way.

These topic aggregations aren’t yet reflected on the home page. But you can find them here:



Similarly for .xml, .json, .ics.

(The directory names is all lowercase. The filenames are whatever you’re using on delicious — most folks use lowercase, but mixed case is possible and both of these are that way.)


Build 396 tweaks the default HTML rendering. With each day, events are now grouped by these time-of-day labels: Morning, Lunch, Afternoon, Evening, Night, WeeHours.


Build 390 starts to make category-based views available. The supported types so far: html and xml.

Example URLs:




Any or all of the categorization methods discussed previously can contribute to these views.

Not yet supported:


(And not yet decided: Does that mean music AND fine-arts? Or music OR fine-arts? And either way, how to express the alternative.)

Bill R: You have some slash-delimited categories, e.g.:


Those won’t work.


Build 388 adds a fourth way to categorize events. In any iCalendar app, you can now use these patterns in the Description field:



This is particularly useful for recurring events. As discussed here, recurring events are a great way to build critical mass because your curation effort keeps paying dividends.

One of the events I found when exploring the search page for Keene is the Monday night bluegrass jam at Harlow’s Pub.

Here’s the description I entered into Windows Live Calendar — which also could have been entered into Google Calendar, or any other iCalendar app:

“The Birch Benders host a Bluegrass picking party at Harlow’s Pub in Peterborough every Monday night – 8 pm until they kick us out (11 or so). url=http://www.harlowspub.com category=music”

Here’s the rendered result:

Mon 08:00 PM Bluegrass night with the Birchbenders (recurring events (live)) (music)

The url=… and category=… patterns can occur anywhere in the description.

I hope this not only opens some doors w/respect to categorization, but also w/respect to finding and adding recurring events, which are a very powerful way to build up critical mass.


With build 386, we have 3 ways to categorize events:

  1. If a source iCalendar feed uses the CATEGORIES property, they’ll be included.
  2. If all of the events from a feed can be categorized, you can name that category in the Delicious metadata, using category=CATEGORY. All events from the feed will inherit it  in the same way that they all inherit the default clickthrough link specified with url=URL.
  3. If all of the events from an Upcoming or Eventful venue can be categorized, you can also name that category in the Delicious metadata. To do that, bookmark the venue URL and use the patterns venue={UPCOMING|EVENTFUL} and category=CATEGORY.

See today’s blog entry for a more detailed explanation.


Build 335 addresses a problem that Dave Witzel noticed when he used Google Calendar as a viewer for the Falls Church combined ICS feed.

The problem was lack of context around the displayed event. The (imperfect) solution, discussed in this blog post, copies the URL for the event (or the default URL, from the url= tag in the delicious metadata), into the LOCATION field.

The blog post has the whole story.


Build 324 adds a service to help curators (or anyone) extract the ICS URL from a web page with an embedded Google Calendar. The writeup is here. The bookmarklet that uses the service is here. To use it directly, for a page like http://www.huntingtoncommunitygardens.com/8.html, do this:


In other words: http://elmcity.cloudapp.net/gcal2ics/ plus the URL of the calendar page without its leading htttp://


Build 313 introduces a major new feature for curators. Read all about it here — A power tool for curators — and let me whether you’re able to make use of it.


The first version of the project FAQ is done. If you know somebody who’s interested in becoming a curator, that page has the information you need.

For a gentler introduction, you can point them to this blog entry which describes the minimal setup required to bootstrap an instance of the calendar aggregator for a location.


To the extent that most people ever subscribe to ICS feeds at all in their personal calendars, I think the best strategy will be to use the aggregator as a conduit to individual feeds that you might want to subscribe — the hockey schedule, the nightclub schedule.

However, build 298 does now publish the merged set of events for each location as a single ICS feed. I’ll be very interested to know who uses these, and how.

I suspect that experiences will vary according to event density. Adding an ICS overlay for Keene into my Outlook calendar actually does seem to be useful, at the current event density. It may already be overwhelming for Ann Arbor or Baltimore.

In any case, the densities will (hopefully) increase for all locations. So I think in the long run the best use of the aggregator will be to collect and promote discovery of individual feeds.


Build 295 lays the foundation for per-location iCalendar feeds that merge all sources of events for each location, but does not yet publish those feeds.

The visible change is on the home page, where events, population, and events/person are now reported. Because these are future events, the numbers change even if no feeds are added. I’d like to include a sparkline in the summary table to visualize those trends.


Today’s version, build 287, focuses on stats reporting. The per-location changes are:

  1. Total events
  2. Population
  3. Ratio of the two

So, for example, this is mashablecity (Providence RI) today:

All events 910, population 48779, events/person 0.02

The per-feed changes are:

  1. If a feed fails to validate, False (in the Valid? column) is a link to the full validation report
  2. Validation errors are captured and reported
  3. Loading errors are captured and reported
  4. The PRODID (Product ID) of the software that wrote the feed is reported.


Build 281, deploying now, is the first fully data-driven version. From now on, I should not have to touch any code to add a new city. The workflow is:

  1. A new curator claims a delicious account, as Matt Gillooly just did with delicious.com/mashablecity.
  2. I bookmark that URL in my own delicious account, using the tag calendarcuration.
  3. On the next cycle, the system queries http://delicious.com/judell/calendarcuration, finds one more curatorial account than before, and rolls it in.

In doing this, I sorted out what the minimal requirement is for account metadata. It is simply — in Matt’s case  — the where slot:

where=providence, ri

Everything else is a slot that you can override from the following defaults:







lat={computed from where}

lon={computed from where}



This version makes the “today’s events” widgets on the home page dynamically selectable. With more locations on board, it will be interested to be able to compare any two, side-by-side, for a given day.


The version deploying now includes these changes:

  • CSS. Although the rendered HTML is only meant as a reference implementation — to be replaced with stuff like Bill’s doing here, it didn’t need to be quite so butt ugly.
  • Baltimore. I’ve added a fourth collection for localist. It’s currently Eventful+Upcoming only, no iCalendar, pending adjustment of the feed tags. Radius is 5 miles because 15 was overwhelming.
  • Metadata. I’m persisting the Delicious metadata into the Azure tablestore. Although Delicious is convenient, not everyone will want to use it. Ed Vielmetti in Ann Arbor would rather use a semantic wiki, which is great. The backend will be a neutral repository for various metadata formats, just as the aggregator is a neutral hub for various calendar formats

With 4 locations running, the update cycle is pushing toward an hour. It won’t be too long before I start running out of hours in the day. But that’s what makes this a nice Azure experiment. The work is naturally divisible and distributable. I’m starting to think about how to hand out tasks to a pool of workers, and coordinate them. Really looking forward to that part, it’ll be interesting!


While implementing Bill’s fix, I found and fixed several problems that were causing both Eventful and iCalendar events to be omitted. So all calendars are now more complete.

I also improved the iCalendar stats page. Now there’s a complete accounting of single events, recurring events, instances of recurring events, and future events.


Bill Rawlinson noticed that the per-feed links weren’t working. That’s because although I defined the metadata mechanism, and he implemented it at http://delicious.com/whyhuntington, I had neglected to actually wire it up! Thanks for noticing, Bill, I’m testing the fix now.

The idea is as follows. Some iCalendar feeds include per-event URLs but many do not. In those cases, we can specify a catch-all link for the feed. Since the feed will already be bookmarked in Delicious, you can do that by adding a name=value tag like so:


> I’m testing the fix now.

Hmm. The test triggered the Delicious rate limit. Which is OK, I’ve been needing to implement caching of external services anyway. So now I will.


The aggregator now includes Upcoming events in and around your location. This feature is controlled by three tags on the metadata URL in your Delicious account. From the Keene example:




19 thoughts on “elmcity project status

  1. Nice, Jon – this is going is a great direction.

    Is there a compact description by reference of the contents of the http://delicious.com/a2cal file that you are pulling from, in particular I assume you are pulling XML or JSON – I don’t want to have to reconstruct the HTML if it’s not needed. It might be as simple as a pointer to the right delicious spec page.

  2. It’s just name-value pairs.

    There are two levels: per-location, and per-feed.

    Per-location, e.g. Keene or Ann Arbor, it looks like this:


    In your semantic wiki that would be:

    |title=events in and around keene

    Then there’s the per-feed level. Here the metadata could be done like so:

    |title=Cheshire Medical Center

    I think you could do this all on one page. You’d wind up with an HTML infobox for the location metadata, plus one for each feed. The generated HTML can’t be easily parsed, but that’s no problem, I could just fetch the Edit link and read the structured source.

  3. Just a note on the Feed metadata; so far we have been adding the optional tag url=http://somwhere.com for any feed that doesn’t include urls for specific events. This provides a default url for all events in that feed.

  4. > we have been adding the optional tag
    > url=http://somwhere.com for any feed
    > that doesn’t include urls for specific
    > events.

    Right. So in the Delicious case, there are really two URLs:

    1. URL of the iCalendar feed

    2. URL of the “home page” for the event source, to be used in case per-event URLs are missing (as they often are)

    Since #1 is implicit — it is the URL that is being bookmarked — the only explicit part is #2, which we’ve been writing as url=http://…

    In another context, like Ed’s semantic wiki, you’d need to spell out both explicitly. Hence:


Leave a Reply