window.addEventListener('WebComponentsReady', function () {
  'use strict';

  // We use Page.js for routing. This is a Micro
  // client-side router inspired by the Express router
  // More info: https://visionmedia.github.io/page.js/

  const DEFAULT_CALENDAR_ID = '*';
  const ESCAPED_DEFAULT_CALENDAR_ID = '\\' + DEFAULT_CALENDAR_ID;

  // Routes
  page('/', scrollToTop, () => {
    eventList(DEFAULT_CALENDAR_ID);
  });

  page('/calendars/' + ESCAPED_DEFAULT_CALENDAR_ID, '/');

  page('/calendars/:calendarId', scrollToTop, data => {
    eventList(data.params.calendarId);
  });

  // add #! before urls
  page({
    hashbang: true,
  });

  // Middleware
  function scrollToTop(ctx, next) {
    app.scrollPageToTop();
    next();
  }

  // Utility functions
  function eventList(selectedCalendar) {
    const PAGE_NAME = 'eventList';
    app.page = PAGE_NAME;
    app.route = PAGE_NAME + ':' + selectedCalendar;
    app.selectCalendar(app.getUrlDecoded(selectedCalendar));
  }
});

@@ -268,74 +268,8 @@
 '*';
-%0A  const ESCAPED_DEFAULT_CALENDAR_ID = '%5C%5C' + DEFAULT_CALENDAR_ID;
 %0A%0A  
@@ -353,33 +353,33 @@
 ;%0A  %7D);%0A%0A  page(
-'
+%60
 /calendars/' + E
@@ -377,20 +377,17 @@
 ars/
-' + ESCAPED_
+$%7Bescape(
 DEFA
@@ -401,16 +401,19 @@
 ENDAR_ID
+)%7D%60
 , '/');%0A
@@ -511,24 +511,47 @@
 Id);%0A  %7D);%0A%0A
+  // Config%0A  page(%7B%0A  
   // add #! 
@@ -562,25 +562,16 @@
 re urls%0A
-  page(%7B%0A
     hash
@@ -708,16 +708,94 @@
 nctions%0A
+  function escape(path) %7B%0A    return path.replace(/%5B%5C*:%5C(%5C)%5D/g, '%5C%5C$&');%0A  %7D%0A%0A
   functi

Clean up routing.js.