diff --git a/aleksis/apps/chronos/fallback_view.py b/aleksis/apps/chronos/fallback_view.py
deleted file mode 100644
index 50103287eeeaca9b276334e10da09da74f31b2bf..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/fallback_view.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from django.contrib.auth.decorators import login_required
-from django.shortcuts import render
-
-
-@login_required
-def fallback(request, *args, **kwargs):
-    return render(request, "timetable/fallback.html")
diff --git a/aleksis/apps/chronos/forms.py b/aleksis/apps/chronos/forms.py
index 871ec7dc0d9fbaf37adcfd48d488b3a5c93f7fd1..d519ba6c303717976801a3326ffca55a9ca670fe 100644
--- a/aleksis/apps/chronos/forms.py
+++ b/aleksis/apps/chronos/forms.py
@@ -1,37 +1,7 @@
 from django import forms
-from django.db.models import Count
-from django.utils.translation import ugettext_lazy as _
+from django_select2.forms import ModelSelect2MultipleWidget
 
-from django_select2.forms import ModelSelect2MultipleWidget, Select2Widget
-
-from aleksis.core.models import Group, Person
-
-from .models import LessonPeriod, LessonSubstitution, Room, Subject
-
-
-class SelectForm(forms.Form):
-    group = forms.ModelChoiceField(
-        queryset=Group.objects.annotate(lessons_count=Count("lessons")).filter(lessons_count__gt=0),
-        label=_("Group"),
-        required=False,
-        widget=Select2Widget,
-    )
-    teacher = forms.ModelChoiceField(
-        queryset=Person.objects.annotate(lessons_count=Count("lessons_as_teacher")).filter(
-            lessons_count__gt=0
-        ),
-        label=_("Teacher"),
-        required=False,
-        widget=Select2Widget,
-    )
-    room = forms.ModelChoiceField(
-        queryset=Room.objects.annotate(lessons_count=Count("lesson_periods")).filter(
-            lessons_count__gt=0
-        ),
-        label=_("Room"),
-        required=False,
-        widget=Select2Widget,
-    )
+from .models import LessonSubstitution
 
 
 class LessonSubstitutionForm(forms.ModelForm):
diff --git a/aleksis/apps/chronos/m2l.py b/aleksis/apps/chronos/m2l.py
deleted file mode 100644
index 754578068a463b132873a9e11ea4bf3ab2963602..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/m2l.py
+++ /dev/null
@@ -1,45 +0,0 @@
-import os
-import subprocess
-
-from debug.models import register_log_with_filename
-from aleksis.settings import BASE_DIR
-
-
-# from .models import register_log_with_filename
-
-
-def convert_markdown_2_latex(s):
-    try:
-        # Write markdown file
-        md_file = open(os.path.join(BASE_DIR, "latex", "m2l.md"), "w", encoding="utf8")
-        md_file.write(s)
-        md_file.close()
-
-        # Execute pandoc to convert markdown to latex
-        bash_command = "pandoc --log={} --from markdown --to latex --output {} {}".format(
-            os.path.join(BASE_DIR, "latex", "m2l.log"),
-            os.path.join(BASE_DIR, "latex", "m2l.tex"),
-            os.path.join(BASE_DIR, "latex", "m2l.md"))
-        process = subprocess.Popen(bash_command.split(), stdout=subprocess.PIPE)
-        output = process.communicate()[0]
-        del output
-
-        # Register log file in debugging tool
-        register_log_with_filename("m2l", "m2l", "m2l.log", process.returncode)
-
-        # Read converted latex from file
-        tex_file = open(os.path.join(BASE_DIR, "latex", "m2l.tex"), "r", encoding="utf8")
-        r = tex_file.read()
-        tex_file.close()
-
-        # Replace some things
-        r = r.replace("\subparagraph", "\subsubsection")
-        r = r.replace("\paragraph", "\subsubsection")
-        r = r.replace("section", "section*")
-
-        # Return latex
-        return r
-    except Exception as e:
-        # Print error
-        print("[MD TO LATEX]", e)
-        return ""
diff --git a/aleksis/apps/chronos/menus.py b/aleksis/apps/chronos/menus.py
index 0b92d8fbb8c620d21b9e95a5c23e9b3ffcd25f66..b82f3556d8f0279b214a0384889bc95a6220007b 100644
--- a/aleksis/apps/chronos/menus.py
+++ b/aleksis/apps/chronos/menus.py
@@ -5,6 +5,7 @@ MENUS = {
         {
             "name": _("Timetables"),
             "url": "#",
+            "icon": "school",
             "root": True,
             "validators": [
                 "menu_generator.validators.is_authenticated",
@@ -12,18 +13,27 @@ MENUS = {
             ],
             "submenu": [
                 {
-                    "name": _("Timetable"),
-                    "url": "timetable",
+                    "name": _("My timetable"),
+                    "url": "my_timetable",
+                    "icon": "person",
+                    "validators": ["menu_generator.validators.is_authenticated"],
+                },
+                {
+                    "name": _("All timetables"),
+                    "url": "all_timetables",
+                    "icon": "grid_on",
                     "validators": ["menu_generator.validators.is_authenticated"],
                 },
                 {
                     "name": _("Daily lessons"),
                     "url": "lessons_day",
+                    "icon": "calendar_today",
                     "validators": ["menu_generator.validators.is_authenticated"],
                 },
                 {
                     "name": _("Substitutions"),
                     "url": "substitutions",
+                    "icon": "update",
                     "validators": ["menu_generator.validators.is_authenticated"],
                 },
             ],
diff --git a/aleksis/apps/chronos/migrations/0001_initial.py b/aleksis/apps/chronos/migrations/0001_initial.py
index 1ef08a22733fa8e67c4ea449e3c3bf32d502a9f6..28eab760977e1f3290581cf1930a09a1c2ad7fc5 100644
--- a/aleksis/apps/chronos/migrations/0001_initial.py
+++ b/aleksis/apps/chronos/migrations/0001_initial.py
@@ -4,7 +4,7 @@ import django.core.validators
 import django.db.models.deletion
 from django.db import migrations, models
 
-import aleksis.apps.chronos.util
+import aleksis.apps.chronos.util.weeks
 import aleksis.core.util.core_helpers
 
 
@@ -229,7 +229,7 @@ class Migration(migrations.Migration):
                 (
                     "week",
                     models.IntegerField(
-                        default=aleksis.apps.chronos.util.CalendarWeek.current_week,
+                        default=aleksis.apps.chronos.util.weeks.CalendarWeek.current_week,
                         verbose_name="Week",
                     ),
                 ),
diff --git a/aleksis/apps/chronos/migrations/0005_remove_school_related.py b/aleksis/apps/chronos/migrations/0005_remove_school_related.py
new file mode 100644
index 0000000000000000000000000000000000000000..ff4239caccbce749d651069a70f3fa7c3281e78a
--- /dev/null
+++ b/aleksis/apps/chronos/migrations/0005_remove_school_related.py
@@ -0,0 +1,74 @@
+# Generated by Django 3.0.2 on 2020-01-10 16:37
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0007_create_admin_user'),
+        ('chronos', '0004_room_name_not_unique'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='lesson',
+            name='school',
+        ),
+        migrations.RemoveField(
+            model_name='lessonperiod',
+            name='school',
+        ),
+        migrations.AlterField(
+            model_name='lesson',
+            name='teachers',
+            field=models.ManyToManyField(related_name='lessons_as_teacher', to='core.Person'),
+        ),
+        migrations.AlterField(
+            model_name='room',
+            name='short_name',
+            field=models.CharField(max_length=10, unique=True, verbose_name='Short name, e.g. room number'),
+        ),
+        migrations.AlterField(
+            model_name='subject',
+            name='abbrev',
+            field=models.CharField(max_length=10, unique=True, verbose_name='Abbreviation of subject in timetable'),
+        ),
+        migrations.AlterField(
+            model_name='subject',
+            name='name',
+            field=models.CharField(max_length=30, unique=True, verbose_name='Long name of subject'),
+        ),
+        migrations.AlterUniqueTogether(
+            name='lessonsubstitution',
+            unique_together={('lesson_period', 'week')},
+        ),
+        migrations.AlterUniqueTogether(
+            name='room',
+            unique_together=set(),
+        ),
+        migrations.AlterUniqueTogether(
+            name='subject',
+            unique_together=set(),
+        ),
+        migrations.AlterUniqueTogether(
+            name='timeperiod',
+            unique_together={('weekday', 'period')},
+        ),
+        migrations.RemoveField(
+            model_name='lessonsubstitution',
+            name='school',
+        ),
+        migrations.RemoveField(
+            model_name='room',
+            name='school',
+        ),
+        migrations.RemoveField(
+            model_name='subject',
+            name='school',
+        ),
+        migrations.RemoveField(
+            model_name='timeperiod',
+            name='school',
+        ),
+    ]
diff --git a/aleksis/apps/chronos/migrations/0006_extended_data.py b/aleksis/apps/chronos/migrations/0006_extended_data.py
new file mode 100644
index 0000000000000000000000000000000000000000..71785e3f7b61e8445ce2a5425952a13be3227552
--- /dev/null
+++ b/aleksis/apps/chronos/migrations/0006_extended_data.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.0.2 on 2020-01-19 13:15
+
+import django.contrib.postgres.fields.jsonb
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('chronos', '0005_remove_school_related'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='lessonperiod',
+            name='extended_data',
+            field=django.contrib.postgres.fields.jsonb.JSONField(default=dict, editable=False),
+        ),
+    ]
diff --git a/aleksis/apps/chronos/model_extensions.py b/aleksis/apps/chronos/model_extensions.py
index 1d93db9aa30cb4436ede00bc67eadc962bdab59f..8f16b828ae522f64daa3df7371871c8afcc4a0c3 100644
--- a/aleksis/apps/chronos/model_extensions.py
+++ b/aleksis/apps/chronos/model_extensions.py
@@ -3,6 +3,13 @@ from aleksis.core.models import Person
 from .models import Lesson, LessonPeriod
 
 
+@Person.property
+def is_teacher(self):
+    """ Check if the user has lessons as a teacher """
+
+    return self.lesson_periods_as_teacher.exists()
+
+
 @Person.property
 def lessons_as_participant(self):
     """ Return a `QuerySet` containing all `Lesson`s this person
diff --git a/aleksis/apps/chronos/models.py b/aleksis/apps/chronos/models.py
index c80de907ef94c21876fadef948001be368f273b0..293b62ba8f886a0689d79121421de7e346bb9473 100644
--- a/aleksis/apps/chronos/models.py
+++ b/aleksis/apps/chronos/models.py
@@ -6,14 +6,16 @@ from typing import Dict, Optional, Tuple, Union
 from django.core import validators
 from django.core.exceptions import ValidationError
 from django.db import models
-from django.db.models import Q
+from django.db.models import F, Q
 from django.http.request import QueryDict
 from django.utils.translation import ugettext_lazy as _
 
+from calendarweek.django import CalendarWeek, i18n_day_names_lazy, i18n_day_abbrs_lazy
+
 from aleksis.core.mixins import ExtensibleModel
 from aleksis.core.models import Group, Person
 
-from .util import CalendarWeek, week_weekday_from_date
+from aleksis.apps.chronos.util.weeks import week_weekday_from_date
 
 
 class LessonPeriodManager(models.Manager):
@@ -30,20 +32,51 @@ class LessonPeriodManager(models.Manager):
         )
 
 
-class LessonPeriodQuerySet(models.QuerySet):
+class LessonSubstitutionManager(models.Manager):
+    """ Manager adding specific methods to lesson substitutions. """
+
+    def get_queryset(self):
+        """ Ensures all related lesson data is loaded as well. """
+
+        return (
+            super()
+            .get_queryset()
+            .select_related(
+                "lesson_period",
+                "lesson_period__lesson",
+                "subject",
+                "lesson_period__period",
+                "room",
+            )
+            .prefetch_related("lesson_period__lesson__groups", "teachers")
+        )
+
+
+class LessonDataQuerySet(models.QuerySet):
     """ Overrides default QuerySet to add specific methods for lesson data. """
 
+    # Overridden in the subclasses. Swaps the paths to the base lesson period
+    # and to any substitutions depending on whether the query is run on a
+    # lesson period or a substitution
+    _period_path = None
+    _subst_path = None
+
     def within_dates(self, start: date, end: date):
         """ Filter for all lessons within a date range. """
 
-        return self.filter(lesson__date_start__lte=start, lesson__date_end__gte=end)
+        return self.filter(
+            **{
+                self._period_path + "lesson__date_start__lte": start,
+                self._period_path + "lesson__date_end__gte": end,
+            }
+        )
 
     def in_week(self, wanted_week: CalendarWeek):
         """ Filter for all lessons within a calendar week. """
 
         return self.within_dates(
-            wanted_week[0] + timedelta(days=1) * (models.F("period__weekday") - 1),
-            wanted_week[0] + timedelta(days=1) * (models.F("period__weekday") - 1),
+            wanted_week[0] + timedelta(days=1) * (F(self._period_path + "period__weekday") - 1),
+            wanted_week[0] + timedelta(days=1) * (F(self._period_path + "period__weekday") - 1),
         ).annotate_week(wanted_week)
 
     def on_day(self, day: date):
@@ -51,7 +84,11 @@ class LessonPeriodQuerySet(models.QuerySet):
 
         week, weekday = week_weekday_from_date(day)
 
-        return self.within_dates(day, day).filter(period__weekday=weekday).annotate_week(week)
+        return (
+            self.within_dates(day, day)
+            .filter(**{self._period_path + "period__weekday": weekday})
+            .annotate_week(week)
+        )
 
     def at_time(self, when: Optional[datetime] = None):
         """ Filter for the lessons taking place at a certain point in time. """
@@ -60,38 +97,45 @@ class LessonPeriodQuerySet(models.QuerySet):
         week, weekday = week_weekday_from_date(now.date())
 
         return self.filter(
-            lesson__date_start__lte=now.date(),
-            lesson__date_end__gte=now.date(),
-            period__weekday=now.isoweekday(),
-            period__time_start__lte=now.time(),
-            period__time_end__gte=now.time(),
+            **{
+                self._period_path + "lesson__date_start__lte": now.date(),
+                self._period_path + "lesson__date_end__gte": now.date(),
+                self._period_path + "period__weekday": now.weekday(),
+                self._period_path + "period__time_start__lte": now.time(),
+                self._period_path + "period__time_end__gte": now.time(),
+            }
         ).annotate_week(week)
 
     def filter_participant(self, person: Union[Person, int]):
         """ Filter for all lessons a participant (student) attends. """
 
         return self.filter(
-            Q(lesson__groups__members=person) | Q(lesson__groups__parent_groups__members=person)
+            Q(**{self._period_path + "lesson__groups__members": person})
+            | Q(**{self._period_path + "lesson__groups__parent_groups__members": person})
         )
 
     def filter_group(self, group: Union[Group, int]):
         """ Filter for all lessons a group (class) regularly attends. """
 
-        return self.filter(Q(lesson__groups=group) | Q(lesson__groups__parent_groups=group))
+        return self.filter(
+            Q(**{self._period_path + "lesson__groups": group})
+            | Q(**{self._period_path + "lesson__groups__parent_groups": group})
+        )
 
     def filter_teacher(self, teacher: Union[Person, int]):
         """ Filter for all lessons given by a certain teacher. """
 
         return self.filter(
-            Q(substitutions__teachers=teacher, substitutions__week=models.F("_week"))
-            | Q(lesson__teachers=teacher)
+            Q(**{self._subst_path + "teachers": teacher, self._subst_path + "week": F("_week"),})
+            | Q(**{self._period_path + "lesson__teachers": teacher})
         )
 
     def filter_room(self, room: Union[Room, int]):
         """ Filter for all lessons taking part in a certain room. """
 
         return self.filter(
-            Q(substitutions__room=room, substitutions__week=models.F("_week")) | Q(room=room)
+            Q(**{self._subst_path + "room": room, self._subst_path + "week": F("_week"),})
+            | Q(**{self._period_path + "room": room})
         )
 
     def annotate_week(self, week: Union[CalendarWeek, int]):
@@ -104,6 +148,11 @@ class LessonPeriodQuerySet(models.QuerySet):
 
         return self.annotate(_week=models.Value(week_num, models.IntegerField()))
 
+
+class LessonPeriodQuerySet(LessonDataQuerySet):
+    _period_path = ""
+    _subst_path = "substitutions__"
+
     def next(self, reference: LessonPeriod, offset: Optional[int] = 1) -> LessonPeriod:
         """ Get another lesson in an ordered set of lessons.
 
@@ -123,7 +172,7 @@ class LessonPeriodQuerySet(models.QuerySet):
 
         return self.annotate_week(week).all()[next_index]
 
-    def filter_from_query(self, query_data: QueryDict):
+    def filter_from_query(self, query_data: QueryDict) -> models.QuerySet:
         """ Apply all filters from a GET or POST query.
 
         This method expects a QueryDict, like the GET or POST attribute of a Request
@@ -139,17 +188,25 @@ class LessonPeriodQuerySet(models.QuerySet):
         if query_data.get("room", None):
             return self.filter_room(int(query_data["room"]))
 
+    def filter_from_type(self, type_: str, pk: int) -> Optional[models.QuerySet]:
+        if type_ == "group":
+            return self.filter_group(pk)
+        elif type_ == "teacher":
+            return self.filter_teacher(pk)
+        elif type_ == "room":
+            return self.filter_room(pk)
+        else:
+            return None
+
+
+class LessonSubstitutionQuerySet(LessonDataQuerySet):
+    _period_path = "lesson_period__"
+    _subst_path = ""
+
 
 class TimePeriod(models.Model):
-    WEEKDAY_CHOICES = [
-        (0, _("Sunday")),
-        (1, _("Monday")),
-        (2, _("Tuesday")),
-        (3, _("Wednesday")),
-        (4, _("Thursday")),
-        (5, _("Friday")),
-        (6, _("Saturday")),
-    ]
+    WEEKDAY_CHOICES = list(enumerate(i18n_day_names_lazy()))
+    WEEKDAY_CHOICES_SHORT = list(enumerate(i18n_day_abbrs_lazy()))
 
     weekday = models.PositiveSmallIntegerField(verbose_name=_("Week day"), choices=WEEKDAY_CHOICES)
     period = models.PositiveSmallIntegerField(verbose_name=_("Number of period"))
@@ -185,7 +242,7 @@ class TimePeriod(models.Model):
 
             wanted_week = CalendarWeek(year=year, week=week_number)
 
-        return wanted_week[self.weekday - 1]
+        return wanted_week[self.weekday]
 
     class Meta:
         unique_together = [["weekday", "period"]]
@@ -262,6 +319,8 @@ class Lesson(models.Model):
 
 
 class LessonSubstitution(models.Model):
+    objects = LessonSubstitutionManager.from_queryset(LessonSubstitutionQuerySet)()
+
     week = models.IntegerField(verbose_name=_("Week"), default=CalendarWeek.current_week)
 
     lesson_period = models.ForeignKey("LessonPeriod", models.CASCADE, "substitutions")
@@ -285,6 +344,14 @@ class LessonSubstitution(models.Model):
         if self.subject and self.cancelled:
             raise ValidationError(_("Lessons can only be either substituted or cancelled."))
 
+    @property
+    def type_(self):
+        # TODO: Add cases events and supervisions
+        if self.cancelled:
+            return "cancellation"
+        else:
+            return "substitution"
+
     class Meta:
         unique_together = [["lesson_period", "week"]]
         ordering = [
@@ -301,7 +368,7 @@ class LessonSubstitution(models.Model):
         ]
 
 
-class LessonPeriod(models.Model, ExtensibleModel):
+class LessonPeriod(ExtensibleModel):
     objects = LessonPeriodManager.from_queryset(LessonPeriodQuerySet)()
 
     lesson = models.ForeignKey("Lesson", models.CASCADE, related_name="lesson_periods")
diff --git a/aleksis/apps/chronos/pdf.py b/aleksis/apps/chronos/pdf.py
deleted file mode 100644
index 16814fcf4adf09edfde5358a46e5968195f5def3..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/pdf.py
+++ /dev/null
@@ -1,52 +0,0 @@
-import os
-import subprocess
-
-from django.template.loader import render_to_string
-
-from aleksis.settings import BASE_DIR
-from debug.models import register_log_with_filename
-
-LOGO_FILENAME = os.path.join(BASE_DIR, "static", "common", "logo.png")
-
-
-def generate_pdf(tex, filename):
-    """Generate a PDF by LaTeX code"""
-
-    # Write LaTeX file
-    tex_file = open(os.path.join(BASE_DIR, "latex", filename + ".tex"), "w", encoding="utf8")
-    tex_file.write(tex)
-    tex_file.close()
-
-    # Execute pdflatex to generate the PDF
-    bash_command = "pdflatex -halt-on-error -output-directory {} {}.tex".format(os.path.join(BASE_DIR, "latex"),
-                                                                                os.path.join(BASE_DIR, "latex",
-                                                                                filename))
-    run_args = list(bash_command.split())
-
-    # Execute two times to get number of last page
-    subprocess.run(run_args, stdout=None)
-    process = subprocess.run(run_args, stdout=None)
-
-    # Register log file in debugging tool
-    register_log_with_filename("latex_{}".format(filename), "latex", "{}.log".format(filename), process.returncode)
-
-def generate_class_tex_header():
-    """Generate LaTeX for a PDF by a substitution table"""
-
-    context = {
-        "LOGO_FILENAME": LOGO_FILENAME,
-    }
-    return render_to_string("timetable/latex/header.tex", context)
-
-
-def generate_class_tex_body(subs, date, header_info, hints=None):
-    """Generate LaTeX for a PDF by a substitution table"""
-
-    context = {
-        "subs": subs,
-        "date": date,
-        "header_info": header_info,
-        "LOGO_FILENAME": LOGO_FILENAME,
-        "hints": hints
-    }
-    return render_to_string("timetable/latex/substitutions.tex", context)
diff --git a/aleksis/apps/chronos/settings.py b/aleksis/apps/chronos/settings.py
deleted file mode 100644
index df9248e2487d7a618c0b16c7d24cdfe30477f0b9..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/settings.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import dbsettings
-from django import forms
-
-from untisconnect.api_helper import get_terms, get_school_years
-
-choices_school_years = []
-school_years = get_school_years()
-for year in school_years:
-    choices_school_years.append((year.id, year.name))
-
-choices_terms = []
-terms = get_terms()
-for term in terms:
-    choices_terms.append((term.id, "{}, #{}: {}".format(term.school_year_id, term.id, term.name)))
-
-
-class UNTISSettings(dbsettings.Group):
-    school_year = dbsettings.PositiveIntegerValue("Schuljahr", widget=forms.Select, choices=choices_school_years)
-    term = dbsettings.IntegerValue("Periode", widget=forms.Select, choices=choices_terms,
-                                   help_text="Bitte wähle oberhalb auch das zur Periode passende Schuljahr aus.")
-
-
-untis_settings = UNTISSettings("UNTIS")
diff --git a/aleksis/apps/chronos/static/css/chronos/timetable.css b/aleksis/apps/chronos/static/css/chronos/timetable.css
index eb0ed9a984d776e326a9bbe56ae09d6b279ee248..c10a7c1942a4e7585d3700f97bc73046ca1b9df1 100644
--- a/aleksis/apps/chronos/static/css/chronos/timetable.css
+++ b/aleksis/apps/chronos/static/css/chronos/timetable.css
@@ -1,13 +1,98 @@
-.chronos-lesson {
-    height: 6em;
+/*+++++++++++*/
+/* Timetable */
+/*+++++++++++*/
+.smart-plan-badge {
+    margin: 5px 20px 5px 0;
 }
 
-ul#timetable_select_form li {
-    dispaly: inline;
+li.active > a > .sidenav-badge {
+    background-color: whitesmoke !important;
+    color: #DA3D56 !important;
+}
+
+.timetable-plan .row, .timetable-plan .col {
+    display: flex;
+    padding: 0 .25rem;
+}
+
+.timetable-plan .row {
+    margin-bottom: .25rem;
+}
+
+.lesson-card, .timetable-title-card {
+    margin: 0;
+    display: flex;
+    flex-grow: 1;
+    min-height: 65px;
+}
+
+.lesson-card .card-content {
+    padding: 0;
+    text-align: center;
+    width: 100%;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+}
+
+.lesson-card .card-content div {
+    padding: 3px;
+    flex: auto;
+    width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.timetable-title-card .card-content {
+    padding: 10px;
+    text-align: center;
+    width: 100%;
+}
+
+.timetable-mobile-title-card {
+    margin-top: 50px;
+    margin-bottom: .60rem;
+}
+
+.timetable-mobile-title-card:first-child {
+    margin-top: -10px;
+    margin-bottom: .60rem;
+}
+
+.timetable-mobile-title-card .card-content {
+    padding: 10px;
+    text-align: center;
+    width: 100%;
+}
+
+.timetable-mobile-title-card .card-content .card-title {
+    font-weight: bold;
+}
+
+table.substitutions td, table.substitutions th {
+    padding: 10px 5px;
+}
+
+.lesson-with-sub {
+    border: 3px solid red;
+    border-radius: 3px;
+}
+
+.lesson-with-sub .badge {
+    margin: 0;
+}
+
+.lesson-with-event {
+    border: 3px solid #9c27b0;
+    border-radius: 3px;
+}
 
+.lesson-card a, .substitutions a {
+    color: inherit;
 }
 
-.chronos-lesson-cancelled {
-    background-color: inherit !important;
-    text-decoration: line-through;
+.btn-timetable-quicklaunch {
+    margin: 1%;
+    width: 30%;
 }
diff --git a/aleksis/apps/chronos/static/js/chronos/date_select.js b/aleksis/apps/chronos/static/js/chronos/date_select.js
new file mode 100644
index 0000000000000000000000000000000000000000..b32309b3e3f4307463dd0b947f94af6cde0356a1
--- /dev/null
+++ b/aleksis/apps/chronos/static/js/chronos/date_select.js
@@ -0,0 +1,25 @@
+var data = getJSONScript("datepicker_data");
+var activeDate = new Date(data.date);
+
+function updateDatepicker() {
+    $("#date").val(formatDate(activeDate));
+}
+
+function loadNew() {
+    window.location.href = data.dest + formatDateForDjango(activeDate);
+}
+
+function onDateChanged() {
+    var str = $("#date").val();
+    var split = str.split(".");
+    activeDate = new Date(split[2], split[1] - 1, split[0]);
+    updateDatepicker();
+    loadNew();
+}
+
+
+$(document).ready(function () {
+    $("#date").change(onDateChanged);
+
+    updateDatepicker();
+});
diff --git a/aleksis/apps/chronos/static/js/chronos/week_select.js b/aleksis/apps/chronos/static/js/chronos/week_select.js
new file mode 100644
index 0000000000000000000000000000000000000000..3d683a886a909d5996c8038267c177e81c545797
--- /dev/null
+++ b/aleksis/apps/chronos/static/js/chronos/week_select.js
@@ -0,0 +1,21 @@
+var data = getJSONScript("week_select");
+
+function goToCalendarWeek(cw, year) {
+    window.location.href = data.dest + year + "/" + cw;
+}
+
+function onCalendarWeekChanged(where) {
+    goToCalendarWeek($(where).val(), data.year);
+}
+
+$(document).ready(function () {
+    $("#calendar-week-1").change(function () {
+        onCalendarWeekChanged("#calendar-week-1");
+    });
+    $("#calendar-week-2").change(function () {
+        onCalendarWeekChanged("#calendar-week-2");
+    });
+    $("#calendar-week-3").change(function () {
+        onCalendarWeekChanged("#calendar-week-3");
+    });
+});
diff --git a/aleksis/apps/chronos/tables.py b/aleksis/apps/chronos/tables.py
index 688db9ccb0c0a8ba3ef296e3ef9580438a248b27..edc64154a65aa01b15b002c8a3f1ce07d9c154e3 100644
--- a/aleksis/apps/chronos/tables.py
+++ b/aleksis/apps/chronos/tables.py
@@ -15,16 +15,16 @@ def _css_class_from_lesson_state(
 ) -> str:
     if record.get_substitution(record._week):
         if record.get_substitution(record._week).cancelled:
-            return "table-danger"
+            return "success"
         else:
-            return "table-warning"
+            return "warning"
     else:
         return ""
 
 
 class LessonsTable(tables.Table):
     class Meta:
-        attrs = {"class": "table table-striped table-bordered table-hover table-responsive-xl"}
+        attrs = {"class": "highlight"}
         row_attrs = {"class": _css_class_from_lesson_state}
 
     period__period = tables.Column(accessor="period__period")
@@ -33,21 +33,6 @@ class LessonsTable(tables.Table):
     lesson__subject = tables.Column(accessor="lesson__subject")
     room = tables.Column(accessor="room")
     edit_substitution = tables.LinkColumn(
-        "edit_substitution", args=[A("id"), A("_week")], text=_("Substitution")
+        "edit_substitution", args=[A("id"), A("_week")], text=_("Substitution"),
+        attrs={"a": {"class": "btn-flat waves-effect waves-orange"}}, verbose_name=_("Manage substitution")
     )
-
-
-class SubstitutionsTable(tables.Table):
-    class Meta:
-        attrs = {"class": "table table-striped table-bordered table-hover table-responsive-xl"}
-
-    lesson_period = tables.Column(verbose_name=_("Lesson"))
-    lesson__groups = tables.Column(
-        accessor="lesson_period__lesson__group_names", verbose_name=_("Groups")
-    )
-    lesson__teachers = tables.Column(
-        accessor="lesson_period__get_teacher_names", verbose_name=_("Teachers")
-    )
-    lesson__subject = tables.Column(accessor="subject")
-    room = tables.Column(accessor="room")
-    cancelled = tables.BooleanColumn(accessor="cancelled", verbose_name=_("Cancelled"))
diff --git a/aleksis/apps/chronos/templates/chronos/all.html b/aleksis/apps/chronos/templates/chronos/all.html
new file mode 100644
index 0000000000000000000000000000000000000000..bedf5ca129d781ff2f13e198714871bf2c4b7b1c
--- /dev/null
+++ b/aleksis/apps/chronos/templates/chronos/all.html
@@ -0,0 +1,50 @@
+{# -*- engine:django -*- #}
+
+{% extends 'core/base.html' %}
+
+{% load i18n static %}
+
+{% block extra_head %}
+  <link rel="stylesheet" href="{% static 'css/chronos/timetable.css' %}">
+{% endblock %}
+
+{% block browser_title %}{% blocktrans %}All timetables{% endblocktrans %}{% endblock %}
+{% block page_title %}{% trans "All timetables" %}{% endblock %}
+
+{% block content %}
+  <div class="row">
+    <div class="col s12 m4">
+      <h5>{% trans "Teachers" %}</h5>
+
+      {% for teacher in teachers %}
+        <a class="waves-effect waves-light btn btn-timetable-quicklaunch primary"
+           href="{% url 'timetable' 'teacher' teacher.pk %}">
+          {{ teacher.short_name }}
+        </a>
+      {% endfor %}
+    </div>
+
+    <div class="col s12 m4">
+      <h5>{% trans "Groups" %}</h5>
+
+      {% for class in classes %}
+        <a class="waves-effect waves-light btn btn-timetable-quicklaunch primary"
+           href="{% url 'timetable' 'group' class.pk %}">
+          {{ class.short_name }}
+        </a>
+      {% endfor %}
+    </div>
+
+    <div class="col s12 m4">
+      <h5>{% trans "Rooms" %}</h5>
+
+      {% for room in rooms %}
+        <a class="waves-effect waves-light btn btn-timetable-quicklaunch primary"
+           href="{% url 'timetable' 'room' room.pk %}">
+          {{ room.short_name }}
+        </a>
+      {% endfor %}
+    </div>
+  </div>
+
+{% endblock %}
diff --git a/aleksis/apps/chronos/templates/chronos/edit_substitution.html b/aleksis/apps/chronos/templates/chronos/edit_substitution.html
index 213ad7a83f2725d6452a63875add14724c7fc1b1..b9164bfb081ab5abae5ee86d6ca50ead558cf01d 100644
--- a/aleksis/apps/chronos/templates/chronos/edit_substitution.html
+++ b/aleksis/apps/chronos/templates/chronos/edit_substitution.html
@@ -1,40 +1,24 @@
 {# -*- engine:django -*- #}
 
 {% extends "core/base.html" %}
-{% load bootstrap4 i18n %}
-
-{% block bootstrap4_extra_head %}
-  {{ block.super }}
-  {{ edit_substitution_form.media.css }}
-{% endblock %}
-
-{% block bootstrap4_extra_script %}
-  {{ block.super }}
-  {{ edit_substitution_form.media.js }}
-{% endblock %}
-
-
-{% block bootstrap4_title %}{% blocktrans %}Edit substitution{% endblocktrans %} - {{ block.super }}{% endblock %}
+{% load material_form i18n %}
 
+{% block browser_title %}{% blocktrans %}Edit substitution.{% endblocktrans %}{% endblock %}
 {% block page_title %}{% blocktrans %}Edit substitution{% endblocktrans %}{% endblock %}
 
 {% block content %}
-  <div class="d-flex justify-content-between">
-    <div class="btn-group" role="group" aria-label="Day actions">
-      {% if substitution %}
-        {# FIXME Respect year as well #}
-        <a href="{% url 'delete_substitution' substitution.lesson_period.id substitution.week %}" class="btn btn-danger">
-          <span class="mdi mdi-delete"></span>
-        </a>
-      {% endif %}
-    </div>
-  </div>
-
   <form method="post">
     {% csrf_token %}
-    {% bootstrap_form edit_substitution_form %}
-    <button type="submit" class="btn btn-dark">
-      <span class="mdi mdi-content-save"></span>
-    </button>
+
+    {% form form=edit_substitution_form %}{% endform %}
+
+    {% include "core/save_button.html" %}
+    {% if substitution %}
+      {# FIXME Respect year as well #}
+      <a href="{% url 'delete_substitution' substitution.lesson_period.id substitution.week %}"
+         class="btn red waves-effect waves-light">
+        <i class="material-icons left">delete</i> {% trans "Delete" %}
+      </a>
+    {% endif %}
   </form>
 {% endblock %}
diff --git a/aleksis/apps/chronos/templates/timetable/hintform.html b/aleksis/apps/chronos/templates/chronos/hint_form.html
similarity index 76%
rename from aleksis/apps/chronos/templates/timetable/hintform.html
rename to aleksis/apps/chronos/templates/chronos/hint_form.html
index 60593e9ae08ea34294e78fc502e8d97fbc663aa7..b0e621311881fd384f02e98211859987223c273a 100644
--- a/aleksis/apps/chronos/templates/timetable/hintform.html
+++ b/aleksis/apps/chronos/templates/chronos/hint_form.html
@@ -1,15 +1,19 @@
-{% include 'partials/header.html' %}
-{% load material_form %}
-{% load martortags %}
-{% load static %}
-{% load widget_tweaks %}
+{# -*- engine:django -*- #}
 
-<main>
+{% extends 'core/base.html' %}
+{% load material_form martortags static widget_tweaks %}
+
+
+{% block content %}
     <h4>
         {% if mode == "new" %}
-            Neuen Hinweis erstellen
+            {% blocktrans %}
+                Create hint
+            {% endblocktrans %}
         {% else %}
-            Hinweis bearbeiten
+            {% blocktrans %}
+                Edit hint
+            {% endblocktrans %}
         {% endif %}
     </h4>
 
@@ -17,13 +21,12 @@
         <div class="alert success">
             <p>
                 <i class="material-icons left">check_circle</i>
-                Der Hinweis wurde erfolgreich erstellt und veröffentlicht. Weiteren Hinweis anlegen oder zur Übersicht
-                zurück?<br>
+                {% blocktrans %}The hint was successfully created and published. Do you want to create another hint or go back to overview?{% endblocktrans %}<br>
                 <a class="btn waves-effect waves-light" href="{% url "timetable_hints" %}"><i
-                        class="material-icons left">arrow_back</i> Zurück zur Übersicht
+                        class="material-icons left">arrow_back</i>{% blocktrans %}Back to overview{% endblocktrans %}
                 </a>
                 <a class="btn waves-effect waves-light green" href="#add-hint"><i class="material-icons left">add</i>
-                    Weiteren Hinweis hinzufügen
+                    {% blocktrans %}Create antoher hint{% endblocktrans %}
                 </a>
             </p>
         </div>
@@ -39,7 +42,7 @@
                 </div>
             </div>
         {% endif %}
-        <h5>Ãœber welchen Zeitraum soll der Hinweis angezeigt werden?
+        <h5>{% blocktrans %}When should the hint be displayed?{% blocktrans %}
             <span class="red-text">*</span>
         </h5>
 
@@ -69,7 +72,7 @@
                 {{ form.to_date|add_class:"datepicker required" }}
             </div>
         </div>
-        <h5>Für wen soll der Hinweis angezeigt werden?
+        <h5>{% blocktrans %}For whom should the hint be displayed?{% endblocktrans %}
             <span class="red-text">*</span>
         </h5>
 
@@ -83,9 +86,9 @@
         {% endif %}
         {{ form.classes.label_tag }}
         {{ form.classes }}
-        <a href="#" id="select-all-classes">Alle auswählen</a>
+        <a href="#" id="select-all-classes">{% blocktrans %}Select all{% endblocktrans %}</a>
         ·
-        <a href="#" id="deselect-all-classes">Alle abwählen</a>
+        <a href="#" id="deselect-all-classes">{% blocktrans %}Unselect all{% endblocktrans %}</a>
         <script type="text/javascript">
             $("#select-all-classes").click(function () {
                 $(".select-wrapper ul li:not(.selected)").click();
@@ -106,11 +109,11 @@
         <p>
             <label>
                 {{ form.teachers }}
-                <span>Für Lehrer anzeigen?</span>
+                <span>{% blocktrans %}Show for teachers?{% endblocktrans %}</span>
             </label>
         </p>
 
-        <h5>Hinweistext
+        <h5>{% blocktrans %}Hint text{% endblocktrans %}
             <span class="red-text">*</span>
         </h5>
         {% if form.text.errors %}
@@ -125,8 +128,7 @@
 
 
         <button type="submit" class="waves-effect waves-light btn green">
-            <i class="material-icons left">save</i> Hinweis {% if mode == "new" %} erstellen und
-            veröffentlichen {% else %} aktualisieren {% endif %}
+            <i class="material-icons left">save</i>{% blocktrans %} {% if mode == "new" %} Create and publish {% else %} Update {% endif %}hint{% endblocktrans %}
         </button>
     </form>
 
@@ -137,6 +139,4 @@
     <script type="text/javascript" src="{% static 'plugins/js/highlight.min.js' %}"></script>
     <script type="text/javascript" src="{% static 'plugins/js/resizable.min.js' %}"></script>
     <script type="text/javascript" src="{% static 'martor/js/martor.min.js' %}"></script>
-</main>
-
-{% include 'partials/footer.html' %}
+{% endblock %}
diff --git a/aleksis/apps/chronos/templates/timetable/hints.html b/aleksis/apps/chronos/templates/chronos/hints.html
similarity index 77%
rename from aleksis/apps/chronos/templates/timetable/hints.html
rename to aleksis/apps/chronos/templates/chronos/hints.html
index bd289497abc631395f82ef67daf6b34937794c23..3c26f0651276472ffc2af4b755e2fc49c657ed08 100644
--- a/aleksis/apps/chronos/templates/timetable/hints.html
+++ b/aleksis/apps/chronos/templates/chronos/hints.html
@@ -1,16 +1,18 @@
-{% include 'partials/header.html' %}
+{# -*- engine:django -*- #}
+
+{% extends 'core/base.html' %}
 {% load material_form %}
 {% load martortags %}
 
-<main>
-    <h4>Hinweismanagement</h4>
+{% block content %}
+    <h4>{% blocktrans %}Hint management{% endblocktrans %}</h4>
 
     {% if msg %}
         <div class="alert success">
             <p>
                 <i class="material-icons left">check_circle</i>
-                Der Hinweis wurde erfolgreich {% if msg == "success_edit" %}gespeichert. {% else %}
-                gelöscht. {% endif %}
+                The hint was successfully {% if msg == "success_edit" %}saved. {% else %}
+                deleted. {% endif %}
             </p>
         </div>
     {% endif %}
@@ -21,15 +23,15 @@
                 <div class="col s12 m4">
                     <a href="{% url 'timetable_add_hint' %}" class="waves-effect waves-light btn green">
                         <i class="material-icons left">add</i>
-                        Neuen Hinweis erstellen
+                        {% blocktrans %}Create hint{% endblocktrans %}
                     </a>
                 </div>
                 <div class="col s12 m8 right-align">
                     <button type="submit" class="waves-effect waves-green btn-flat">
-                        <i class="material-icons left">refresh</i> Filter aktualisieren
+                        <i class="material-icons left">refresh</i>{% blocktrans %}Refresh filter{% endblocktrans %}
                     </button>
                     <a class="waves-effect waves-red btn-flat " href="{% url "timetable_hints" %}">
-                        <i class="material-icons left">clear</i> Filter entfernen
+                        <i class="material-icons left">clear</i>{% blocktrans }Clear filter{% endblocktrans %}
                     </a>
                 </div>
             </div>
@@ -44,12 +46,12 @@
                 <div class="collapsible-header row no-margin">
 
                     <div class="col s10">
-                        <strong>{{ hint.from_date }} &mdash; {{ hint.to_date }}</strong> für
+                        <strong>{{ hint.from_date }} &mdash; {{ hint.to_date }}</strong>{% blocktrans %}Hint for{% endblocktrans %}
                         <strong>
                             {{ hint.classes_formatted }}
                         </strong>
                         {% if hint.teachers %}
-                            <span class="badge new green no-float no-margin">Lehrkräfte</span>
+                            <span class="badge new green no-float no-margin">{% blocktrans %}Teachers{% endblocktrans %}</span>
                         {% endif %}
                     </div>
                     <div class="col s2">
@@ -63,12 +65,12 @@
                         <a class="btn-flat waves-effect waves-green green-text"
                            href="{% url "timetable_edit_hint" hint.id %}">
                             <i class="material-icons left">edit</i>
-                            <span class="hide-on-small-only">Bearbeiten</span>
+                            <span class="hide-on-small-only">{% blocktrans %}Edit{% endblocktrans %}</span>
                         </a>
                         <a class="btn-flat waves-effect waves-red red-text delete-button"
                            href="{% url "timetable_delete_hint" hint.id %}">
                             <i class="material-icons left">delete</i>
-                            <span class="hide-on-small-only">Löschen</span>
+                            <span class="hide-on-small-only">{% blocktrans %}Delete{% endblocktrans %}</span>
                         </a>
 
                     </div>
@@ -80,6 +82,4 @@
             </li>
         {% endfor %}
     </ul>
-</main>
-
-{% include 'partials/footer.html' %}
+{% endblock %}
diff --git a/aleksis/apps/chronos/templates/chronos/lessons_day.html b/aleksis/apps/chronos/templates/chronos/lessons_day.html
index 1f025c3b39ace7cd2ca3f6bdecac611e33d37a84..46feace7d131e3cee51163e43bdbd548c40db120 100644
--- a/aleksis/apps/chronos/templates/chronos/lessons_day.html
+++ b/aleksis/apps/chronos/templates/chronos/lessons_day.html
@@ -1,11 +1,27 @@
 {# -*- engine:django -*- #}
 
-{% extends "core/turnable.html" %}
-{% load bootstrap4 i18n %}
+{% extends "core/base.html" %}
+{% load i18n %}
+
+
 {% load render_table from django_tables2 %}
 
-{% block bootstrap4_title %}{% blocktrans %}Lessons{% endblocktrans %} - {{ block.super }}{% endblock %}
+{% block browser_title %}{% blocktrans %}Lessons{% endblocktrans %}{% endblock %}
+{% block no_page_title %}{% endblock %}
+
+{% block content %}
+  <script type="text/javascript">
+    var dest = Urls.lessonsDay();
+  </script>
+
+  <div class="row no-margin">
+    <div class="col s12 m6 l8 no-padding">
+      <h4>{% blocktrans %}Lessons{% endblocktrans %} {{ day|date:"l" }}, {{ day }}</h4>
+    </div>
+    <div class="col s12 m6 l4 no-padding">
+      {% include "chronos/partials/datepicker.html" %}
+    </div>
+  </div>
 
-{% block current_content %}
   {% render_table lessons_table %}
 {% endblock %}
diff --git a/aleksis/apps/chronos/templates/chronos/my_timetable.html b/aleksis/apps/chronos/templates/chronos/my_timetable.html
new file mode 100644
index 0000000000000000000000000000000000000000..90adf8fb4a2f0c04eeb605ae7ff6b271a6ab6141
--- /dev/null
+++ b/aleksis/apps/chronos/templates/chronos/my_timetable.html
@@ -0,0 +1,68 @@
+{# -*- engine:django -*- #}
+
+{% extends 'core/base.html' %}
+
+{% load i18n static %}
+
+{% block extra_head %}
+  <link rel="stylesheet" href="{% static 'css/chronos/timetable.css' %}">
+{% endblock %}
+
+{% block browser_title %}{% blocktrans %}My timetable{% endblocktrans %}{% endblock %}
+{% block no_page_title %}{% endblock %}
+
+{% block content %}
+  <div class="row no-margin">
+    <div class="col m12 s12 l6 xl4">
+      <h4>
+        {% trans "My timetable" %} <i>{{ el }}</i>
+        <span class="badge new primary-color ">{% trans "SMART PLAN" %}</span>
+      </h4>
+      <a class="btn-flat waves-effect waves-light" href="{% url "timetable" super.type super.el.pk %}">
+        {% trans "Show week timetable for" %} {{ super.el.short_name }}
+      </a>
+    </div>
+  </div>
+
+  <div class="row nomargin">
+    <div class="col m12 s12 l6 xl4">
+      {#            {% include "timetable/hintsinplan.html" %}#}
+    </div>
+  </div>
+
+  <div class="row">
+    <div class="timetable-plan col s12 m12 xl4">
+
+      {#  Date #}
+
+      <div class="row">
+        <div class="col s12">
+          <div class="card timetable-title-card">
+            <div class="card-content">
+                    <span class="card-title">
+                        {% include "chronos/partials/datepicker.html" with display_date_only=1 %}
+{#                      {% if holiday %}#}
+{#                        <span class="badge new blue center-align holiday-badge">{{ holiday.0 }}</span>#}
+{#                      {% endif %}#}
+                    </span>
+            </div>
+          </div>
+
+        </div>
+      </div>
+      {#  Lessons #}
+      {% for period, lessons in lesson_periods.items %}
+        <div class="row">
+          <div class="col s4">
+            {% include "chronos/partials/period_time.html" with period=period periods=periods %}
+          </div>
+          <div class="col s8">
+            {# A lesson #}
+            {% include "chronos/partials/lesson.html" with lessons=lessons %}
+          </div>
+        </div>
+      {% endfor %}
+
+    </div>
+  </div>
+{% endblock %}
diff --git a/aleksis/apps/chronos/templates/chronos/partials/datepicker.html b/aleksis/apps/chronos/templates/chronos/partials/datepicker.html
new file mode 100644
index 0000000000000000000000000000000000000000..ede1fb06e37da69590468018bec6ca5384bd459f
--- /dev/null
+++ b/aleksis/apps/chronos/templates/chronos/partials/datepicker.html
@@ -0,0 +1,30 @@
+{% load static %}
+
+{% if not display_date_only %}
+  <script type="text/javascript" src="{% static "js/helper.js" %}"></script>
+  {{ datepicker|json_script:"datepicker_data" }}
+  <script type="text/javascript" src="{% static "js/chronos/date_select.js" %}"></script>
+{% endif %}
+
+<div class="col s2 no-padding">
+    <a class="waves-effect waves-teal btn-flat btn-flat-medium left" href="{{ url_prev }}">
+        <i class="material-icons center">navigate_before</i>
+    </a>
+</div>
+
+{% if display_date_only %}
+    <div class="col s8">
+    <span class="card-title center-block" id="date">
+        {{ day|date:"l" }}, {{ day }}
+    </span>
+    </div>
+{% else %}
+    <div class="col s8 no-padding">
+        <input type="text" class="datepicker center-align" id="date">
+    </div>
+{% endif %}
+<div class="col s2 no-padding">
+    <a class="waves-effect waves-teal btn-flat btn-flat-medium right" href="{{ url_next }}">
+        <i class="material-icons center">navigate_next</i>
+    </a>
+</div>
diff --git a/aleksis/apps/chronos/templates/chronos/partials/groups.html b/aleksis/apps/chronos/templates/chronos/partials/groups.html
new file mode 100644
index 0000000000000000000000000000000000000000..3ccfc00c4f6789fe4878880179e837408601c6ba
--- /dev/null
+++ b/aleksis/apps/chronos/templates/chronos/partials/groups.html
@@ -0,0 +1,5 @@
+{% for group in groups %}
+  <a href="{% url "timetable" "group" group.pk %}">
+    {{ group.short_name }}{% if not forloop.last %},{% endif %}
+  </a>
+{% endfor %}
diff --git a/aleksis/apps/chronos/templates/timetable/hintsinsub.html b/aleksis/apps/chronos/templates/chronos/partials/hints/substitutions.html
similarity index 100%
rename from aleksis/apps/chronos/templates/timetable/hintsinsub.html
rename to aleksis/apps/chronos/templates/chronos/partials/hints/substitutions.html
diff --git a/aleksis/apps/chronos/templates/timetable/hintsinsubprint.html b/aleksis/apps/chronos/templates/chronos/partials/hints/substitutions_print.html
similarity index 100%
rename from aleksis/apps/chronos/templates/timetable/hintsinsubprint.html
rename to aleksis/apps/chronos/templates/chronos/partials/hints/substitutions_print.html
diff --git a/aleksis/apps/chronos/templates/timetable/hintsinplan.html b/aleksis/apps/chronos/templates/chronos/partials/hints/timetable.html
similarity index 100%
rename from aleksis/apps/chronos/templates/timetable/hintsinplan.html
rename to aleksis/apps/chronos/templates/chronos/partials/hints/timetable.html
diff --git a/aleksis/apps/chronos/templates/chronos/partials/lesson.html b/aleksis/apps/chronos/templates/chronos/partials/lesson.html
new file mode 100644
index 0000000000000000000000000000000000000000..8dc4f9fb2f264cfe188241502d298cf3e095ccf3
--- /dev/null
+++ b/aleksis/apps/chronos/templates/chronos/partials/lesson.html
@@ -0,0 +1,131 @@
+{% load i18n %}
+
+<div class="card lesson-card">
+  <div class="card-content">
+
+    {# Every element of the lesson #}
+    {% for lesson_period in lessons %}
+      <div style="
+              {# Display background color only if no badge exists and it is not the old room and there are no holidays #}
+              {% if not lesson_period.get_substitution.cancelled and not lesson_period.is_hol %}
+                {% if not lesson_period.room != lesson_period.get_room or type != 1 %}
+                  {% if lesson_period.lesson.subject.colour_fg %}
+                    color: {{ lesson_period.lesson.subject.colour_fg }};
+                  {% endif %}
+                  {% if lesson_period.lesson.subject.colour_bg %}
+                    background-color: {{ lesson_period.lesson.subject.colour_bg }};
+                  {% endif %}
+                {% endif %}
+              {% endif %}
+              "
+              {# Add CSS class for sub when it's a sub #}
+           class="{% if lesson_period.get_substitution and smart %}{% if lesson_period.substitution.table.is_event %}lesson-with-event{% else %}lesson-with-sub{% endif %}{% endif %}"
+      >
+        <p>
+          {% if lesson_period.is_hol and smart %}
+            {# Do nothing #}
+          {% elif lesson_period.get_substitution and smart %}
+            {% with sub=lesson_period.get_substitution %}
+              {# SUBSTITUTION #}
+              {% if type == "room" and lesson_period.room != lesson_period.get_room %}
+                {# When it's the old room, let it empty #}
+
+              {% elif lesson_period.get_substitution.cancelled %}
+                {# When a badge (cancellation, etc.) exists, then display it with the teacher#}
+
+                {# Class or room > Display teacher #}
+                {% if type == "group" or type == "room" and lesson_period.lesson.teachers.all %}
+                  {% include "chronos/partials/teachers.html" with teachers=lesson_period.lesson.teachers.all %}<br/>
+                {% endif %}
+
+                {# Badge #}
+                <span class="badge new green darken-2">{% trans "Cancelled" %}</span>
+
+              {% else %}
+                {# Display sub #}
+
+                {# Teacher or room > display classes #}
+                {% if type == "teacher" or type == "room" %}
+                  {% include "chronos/partials/groups.html" with groups=lesson_period.lesson.groups.all %}
+                {% endif %}
+
+                {# Display teacher with tooltip #}
+                {% include "chronos/partials/subs/teachers.html" %}
+
+                {# Display subject #}
+                {% include "chronos/partials/subs/subject.html" %}
+
+                {# Teacher or class > display room #}
+                {% if type == "teacher" or type == "group" %}
+                  {% include "chronos/partials/subs/room.html" %}
+                {% endif %}
+              {% endif %}
+
+
+              {# When it isn't a room or the old plan, then display the extra text (e. g. work orders) AND NOT A EVENT#}
+              {% if not lesson_period.substitution.table.is_event %}
+                {% if not type == "room"  or not lesson_period.is_old %}
+                  <br>
+                  <small>
+                    <em>{{ lesson_period.substitution.table.text|default:"" }}</em>
+                  </small>
+                {% endif %}
+              {% endif %}
+              {# Display the extra text for events #}
+              {% if lesson_period.substitution.table.is_event %}
+                {% if type == 0 and lesson_period.substitution.table.classes == "" and lesson_period.substitution.table.rooms|length == 0 and lesson_period.substitutions.table.teachers|length == 0 %}
+                  <em>{{ lesson_period.substitution.table.text|default:"" }}</em>
+                {% elif type == 2 and  lesson_period.substitution.table.teachers|length == 0  and  lesson_period.substitution.table.rooms|length == 0 %}
+                  <em>{{ lesson_period.substitution.table.text|default:"" }}</em>
+                {% elif type == 1  and  lesson_period.substitution.table.teachers|length == 0 and lesson_period.substitution.table.classes == "" %}
+                  <em>{{ lesson_period.substitution.table.text|default:"" }}</em>
+                {% else %}
+                  <br>
+                  <small>
+                    <em>{{ lesson_period.substitution.table.text|default:"" }}</em>
+                  </small>
+                {% endif %}
+              {% endif %}
+            {% endwith %}
+
+
+          {% else %}
+            {# Normal plan #}
+
+            {# Teacher or room > Display classes #}
+            {% if type == "teacher" or type == "room" %}
+              {#                            {{ element_container.element.classes }}#}
+              {% if lesson_period.lesson.groups %}
+                {% include "chronos/partials/groups.html" with groups=lesson_period.lesson.groups.all %}
+              {% endif %}
+            {% endif %}
+
+            {# Class or room > Display teacher #}
+            {% if type == "room" or type == "group" %}
+              {% include "chronos/partials/teachers.html" with teachers=lesson_period.lesson.teachers.all %}
+            {% endif %}
+
+            {# Display subject #}
+            <strong>
+              <span data-position="bottom" class="tooltipped"
+                    data-tooltip="{{ lesson_period.lesson.subject.name }}">{{ lesson_period.lesson.subject.abbrev }}</span>
+            </strong>
+
+            {# Teacher or class > Display room #}
+            {% if type == "teacher" or type == "group" %}
+              {% if lesson_period.room %}
+                <span class="tooltipped" data-position="bottom"
+                      data-tooltip="{{ lesson_period.room.name }}">
+                                  <a href="{% url "timetable" "room" lesson_period.room.pk %}">
+                                        {{ lesson_period.room.short_name }}
+                                    </a>
+                            </span>
+              {% endif %}
+            {% endif %}
+          {% endif %}
+        </p>
+      </div>
+
+    {% endfor %}
+  </div>
+</div>
diff --git a/aleksis/apps/chronos/templates/chronos/partials/period_time.html b/aleksis/apps/chronos/templates/chronos/partials/period_time.html
new file mode 100644
index 0000000000000000000000000000000000000000..ebd76dab6393c83332e07c1b194248480846323f
--- /dev/null
+++ b/aleksis/apps/chronos/templates/chronos/partials/period_time.html
@@ -0,0 +1,20 @@
+{% load data_helpers %}
+
+<div class="card timetable-title-card">
+  <div class="card-content">
+
+    {# Lesson number #}
+    <span class="card-title left">
+                                {{ period }}.
+                            </span>
+
+    {# Time dimension of lesson #}
+    <div class="right timetable-time grey-text text-darken-2">
+      {% with period_obj=periods|get_dict:period %}
+        <span>{{ period_obj.0|time }}</span>
+        <br/>
+        <span>{{ period_obj.1|time }}</span>
+      {% endwith %}
+    </div>
+  </div>
+</div>
diff --git a/aleksis/apps/chronos/templates/chronos/partials/subs/room.html b/aleksis/apps/chronos/templates/chronos/partials/subs/room.html
new file mode 100644
index 0000000000000000000000000000000000000000..cf637b92303dfe31d1c19dc781809f1c3c10dac3
--- /dev/null
+++ b/aleksis/apps/chronos/templates/chronos/partials/subs/room.html
@@ -0,0 +1,47 @@
+{% if not sub.is_event %}
+  {% if sub.sub.type == 3 %}
+    {# Supervisement #}
+    {{ sub.sub.corridor.name }}
+  {% elif sub.sub.type == 1 or sub.sub.type == 2 %}
+    {# Canceled lesson: no room #}
+  {% elif sub.room and sub.lesson_period.room %}
+    {# New and old room available #}
+    <span class="tooltipped" data-position="bottom"
+          data-tooltip="{{ sub.lesson_period.room.name }} → {{ sub.lesson_period.room.name }}">
+            <a href="{% url "timetable" "room" sub.lesson_period.room.pk %}">
+                <s>{{ sub.lesson_period.room.short_name }}</s>
+            </a>
+            →
+            <a href="{% url "timetable" "room" sub.room.pk %}">
+                <strong>{{ sub.room.short_name }}</strong>
+            </a>
+        </span>
+  {% elif sub.room and not sub.lesson_period.room %}
+    {# Only new room available #}
+    <span class="tooltipped" data-position="bottom"
+          data-tooltip="{{ sub.room.name }}">
+            <a href="{% url "timetable" "room" sub.room.pk %}">
+                {{ sub.room.short_name }}
+            </a>
+        </span>
+  {% elif not sub.room and not sub.lesson_period.room %}
+    {# Nothing to view #}
+  {% else %}
+    {# Only old room available #}
+    <span class="tooltipped" data-position="bottom"
+          data-tooltip="{{ sub.lesson_period.room.name }}">
+            <a href="{% url "timetable" "room" sub.lesson_period.room.pk %}">
+                {{ sub.lesson_period.room.short_name }}
+            </a>
+        </span>
+  {% endif %}
+{% else %}
+  {% for room in sub.rooms %}
+    <span class="tooltipped" data-position="bottom"
+          data-tooltip="{{ room.name }}">
+            <a href="{% url "timetable_smart_plan" "room" room.id %}">
+                <strong>{{ room.short_name }}{% if not forloop.last %},{% endif %}</strong>
+            </a>
+        </span>
+  {% endfor %}
+{% endif %}
diff --git a/aleksis/apps/chronos/templates/chronos/partials/subs/subject.html b/aleksis/apps/chronos/templates/chronos/partials/subs/subject.html
new file mode 100644
index 0000000000000000000000000000000000000000..6fe8eb5a02bb7a6afb75adf50012efa9d2712239
--- /dev/null
+++ b/aleksis/apps/chronos/templates/chronos/partials/subs/subject.html
@@ -0,0 +1,28 @@
+{% load i18n %}
+
+{% if not sub.sub.is_event %}
+  {% if sub.sub.type == 3 %}
+    <strong>{% trans "Supervision" %}</strong>
+  {% elif not sub.lesson_period.lesson.subject and not sub.subject %}
+  {% elif sub.sub.type == 1 or sub.sub.type == 2 %}
+    <span data-position="bottom" class="tooltipped" data-tooltip="{{ sub.lesson_period.lesson.subject.name }}">
+      <s>{{ sub.lesson_period.lesson.subject.abbrev }}</s>
+    </span>
+  {% elif sub.subject and sub.lesson_period.lesson.subject %}
+    <span data-position="bottom" class="tooltipped" data-tooltip="{{ sub.lesson_period.lesson.subject.name }}">
+      <s>{{ sub.lesson_period.lesson.subject.abbrev }}</s>
+    </span>
+    →
+    <span data-position="bottom" class="tooltipped" data-tooltip="{{ sub.subject.name }}">
+      <strong>{{ sub.subject.abbrev }}</strong>
+    </span>
+  {% elif sub.subject and not sub.lesson_period.lesson.subject %}
+    <span data-position="bottom" class="tooltipped" data-tooltip="{{ sub.subject.name }}">
+      <strong>{{ sub.subject.abbrev }}</strong>
+    </span>
+  {% else %}
+    <span data-position="bottom" class="tooltipped" data-tooltip="{{ sub.lesson_period.lesson.subject.name }}">
+      <strong>{{ sub.lesson_period.lesson.subject.abbrev }}</strong>
+    </span>
+  {% endif %}
+{% endif %}
diff --git a/aleksis/apps/chronos/templates/chronos/partials/subs/teachers.html b/aleksis/apps/chronos/templates/chronos/partials/subs/teachers.html
new file mode 100644
index 0000000000000000000000000000000000000000..ec17d8b811cfad34c1cad90d2a3302aa5752ba53
--- /dev/null
+++ b/aleksis/apps/chronos/templates/chronos/partials/subs/teachers.html
@@ -0,0 +1,19 @@
+{% if not sub.is_event %}
+  {% if sub.sub.type == 1 and sub.lesson_period.lesson.teachers.all %}
+    {% include "chronos/partials/teachers.html" with teachers=sub.lesson_period.lesson.teachers.all %}
+  {% elif sub.teachers.all and sub.lesson_period.lesson.teachers.all %}
+    <s>
+      {% include "chronos/partials/teachers.html" with teachers=sub.lesson_period.lesson.teachers.all %}
+    </s>
+    →
+    <strong>
+      {% include "chronos/partials/teachers.html" with teachers=sub.teachers.all %}
+    </strong>
+  {% elif sub.teachers.all and not sub.lesson_period.lesson.teachers.all %}
+    {% include "chronos/partials/teachers.html" with teachers=sub.teachers.all %}
+  {% elif sub.lesson_period.lesson.teachers.all %}
+    {% include "chronos/partials/teachers.html" with teachers=sub.lesson_period.lesson.teachers.all %}
+  {% endif %}
+{% else %}
+  {% include "chronos/partials/teachers.html" with teachers=sub.teachers.all %}
+{% endif %}
diff --git a/aleksis/apps/chronos/templates/chronos/partials/teachers.html b/aleksis/apps/chronos/templates/chronos/partials/teachers.html
new file mode 100644
index 0000000000000000000000000000000000000000..d7ec97197f1309c651d0a8c07b0d1e387ecaade8
--- /dev/null
+++ b/aleksis/apps/chronos/templates/chronos/partials/teachers.html
@@ -0,0 +1,8 @@
+{% for teacher in teachers %}
+  <span data-position="bottom" class="tooltipped"
+        data-tooltip="{{ teacher }}">
+      <a href="{% url "timetable" "teacher" teacher.pk %}">
+          {{ teacher.short_name }}{% if not forloop.last %},{% endif %}
+      </a>
+  </span>
+{% endfor %}
diff --git a/aleksis/apps/chronos/templates/chronos/substitutions.html b/aleksis/apps/chronos/templates/chronos/substitutions.html
index cd18828b5366a38f5ae2da521824229f691af6a9..2d0c99044c421e22d9bea5a3ac66733ee471c7fa 100644
--- a/aleksis/apps/chronos/templates/chronos/substitutions.html
+++ b/aleksis/apps/chronos/templates/chronos/substitutions.html
@@ -1,11 +1,117 @@
 {# -*- engine:django -*- #}
 
-{% extends "core/turnable.html" %}
-{% load bootstrap4 i18n %}
-{% load render_table from django_tables2 %}
+{% extends 'core/base.html' %}
 
-{% block bootstrap4_title %}{% blocktrans %}Substitutions{% endblocktrans %} - {{ block.super }}{% endblock %}
+{% load i18n static %}
+
+{% block extra_head %}
+  <link rel="stylesheet" href="{% static 'css/chronos/timetable.css' %}">
+{% endblock %}
+
+{% block browser_title %}{% blocktrans %}Substitutions{% endblocktrans %}{% endblock %}
+{% block no_page_title %}{% endblock %}
+
+{% block content %}
+  <div class="row no-margin">
+    <div class="col s10 m6 no-padding">
+      <h4>{% trans "Substitutions" %}</h4>
+    </div>
+    <div class="col s2 m6 right align-right print-icon">
+      {#            <a class="waves-effect waves-teal btn-flat btn-flat-medium right"#}
+      {#               href="#}
+      {#                    {% if debug %}#}
+      {#                        {% url "timetable_substitutions_pdf_date" date|date:"Y-m-d" %}#}
+      {#                    {% else %}#}
+      {#                       {% url "timetable_substitutions_pdf" %}#}
+      {#                    {% endif %}#}
+      {#                    ">#}
+      {#                <i class="material-icons center">print</i>#}
+      {#            </a>#}
+    </div>
+  </div>
+
+  <div class="row no-print">
+    <div class="col s12 m6 l8">
+      {% if header_info.is_box_needed %}
+        <div class="card">
+          <div class="card-content">
+            {% for row in header_info.rows %}
+              <div class="row no-margin">
+                <div class="col s3">
+                  <strong class="truncate">{{ row.0 }}</strong>
+                </div>
+                <div class="col s9">
+                  {{ row.1 }}
+                </div>
+              </div>
+            {% endfor %}
+          </div>
+        </div>
+      {% endif %}
+
+      {#            {% include "chronos/hintsinsub.html" %}#}
+    </div>
+    <div class="col s12 m6 l4 no-padding">
+      {% include "chronos/partials/datepicker.html" %}
+    </div>
+  </div>
+
+  <h5 class="hide-on-small-and-down">{{ day|date:"l" }}, {{ day }}</h5>
+
+  <table class="substitutions striped responsive-table">
+    <thead>
+    <tr>
+      <th><i class="material-icons">people</i></th>
+      <th><i class="material-icons">access_time</i></th>
+      <th>{% trans "Teacher" %}</th>
+      <th>{% trans "Subject" %}</th>
+      <th>{% trans "Room" %}</th>
+      <th>{% trans "Notes" %}</th>
+      <th></th>
+    </tr>
+    </thead>
+    <tbody>
+    {% if not substitutions %}
+      <td colspan="7">
+        <p class="flow-text center">
+          {% blocktrans %}No substitutions available.{% endblocktrans %}
+        </p>
+      </td>
+    {% endif %}
+    {% for sub in substitutions %}
+      <tr class="{% if sub.type_ == "cancellation" %}green-text{% else %}black-text{% endif %}"> {# TODO: Extend support for blue and purple (supervisions and events) #}
+        <td>
+          {% include "chronos/partials/groups.html" with groups=sub.lesson_period.lesson.groups.all %}
+        </td>
+        <td>
+          <strong>
+            {{ sub.lesson_period.period.period }}.
+          </strong>
+        </td>
+        <td>
+          {% include "chronos/partials/subs/teachers.html" %}
+        </td>
+        <td>
+          {% include "chronos/partials/subs/subject.html" %}
+        </td>
+        <td>
+          {% include "chronos/partials/subs/room.html" %}
+        </td>
+        <td>
+          {% if sub.cancelled %}
+            {# TODO: Support other cases#}
+            <span class="badge new green hide-on-med-and-up">{% trans "Cancelled" %}</span>
+          {% endif %}
+{#          <em>{{ sub.text|default:"" }}</em>#}
+        </td>
+        <td class="hide-on-small-and-down">
+          {% if sub.cancelled %}
+            <span class="badge new green darken-2">{% trans "Cancelled" %}</span>
+          {% endif %}
+        </td>
+      </tr>
+    {% endfor %}
+    </tbody>
+  </table>
 
-{% block current_content %}
-  {% render_table substitutions_table %}
 {% endblock %}
diff --git a/aleksis/apps/chronos/templates/timetable/substitutionprint.html b/aleksis/apps/chronos/templates/chronos/substitutions_print.html
similarity index 84%
rename from aleksis/apps/chronos/templates/timetable/substitutionprint.html
rename to aleksis/apps/chronos/templates/chronos/substitutions_print.html
index 39363d68a5b46e52b00d3099716362fb8aa9784e..9f30bd141cb846f71b88e5fb3cb6a9e766ecf271 100644
--- a/aleksis/apps/chronos/templates/timetable/substitutionprint.html
+++ b/aleksis/apps/chronos/templates/chronos/substitutions_print.html
@@ -1,8 +1,11 @@
+{# -*- engine:django -*- #}
+
+{% extends 'core/base.html' %}
 {% load common %}
-{% include 'partials/paper/header.html' %}
 
+{% block content %}
 <script type="text/javascript">
-    var dest = "/timetable/substitutions/";
+    var dest = Urls.substitutions();
 </script>
 
 <style>
@@ -20,7 +23,7 @@
 </style>
 
 {% for c in days %}
-    <h4>Vertretungen {{ c.date|date:"l, j. F Y" }}</h4>
+    <h4>Substitutions {{ c.date|date" }}</h4>
 
 
     {% include "timetable/hintsinsubprint.html" %}
@@ -45,10 +48,10 @@
         <tr>
             <th><i class="material-icons">people</i></th>
             <th><i class="material-icons">access_time</i></th>
-            <th>Lehrer</th>
-            <th>Fach</th>
-            <th>Raum</th>
-            <th>Hinweis</th>
+            <th>{% blocktrans %}Teachers{% endblocktrans %}</th>
+            <th>{% blocktrans %}Subject{% endblocktrans %}</th>
+            <th>{% blocktrans %}Room{% endblocktrans %}</th>
+            <th>{% blocktrans %}Hint{% endblocktrans %}</th>
             <th></th>
         </tr>
         </thead>
@@ -56,7 +59,7 @@
         {% if not c.sub_table %}
             <td colspan="7">
                 <p class="flow-text center">
-                    Keine Vertretungen vorhanden
+                    {% blocktrans %}No existing substitutions{% endblocktrans %}
                 </p>
             </td>
         {% endif %}
@@ -105,6 +108,4 @@
     </table>
 
 {% endfor %}
-
-
-{% include 'partials/paper/footer.html' %}
+{% endblock %}
diff --git a/aleksis/apps/chronos/templates/chronos/timetable.html b/aleksis/apps/chronos/templates/chronos/timetable.html
new file mode 100644
index 0000000000000000000000000000000000000000..4fa91ac68f3ef7c34678ae9c94958f324ca43380
--- /dev/null
+++ b/aleksis/apps/chronos/templates/chronos/timetable.html
@@ -0,0 +1,209 @@
+{# -*- engine:django -*- #}
+
+{% extends 'core/base.html' %}
+
+{% load data_helpers static i18n %}
+
+{% block extra_head %}
+  <link rel="stylesheet" href="{% static 'css/chronos/timetable.css' %}">
+{% endblock %}
+
+{% block browser_title %}{% blocktrans %}Timetable{% endblocktrans %}{% endblock %}
+{% block content %}
+
+  {% if smart %}
+    <script type="text/javascript" src="{% static "js/helper.js" %}"></script>
+    {{ week_select|json_script:"week_select" }}
+    <script type="text/javascript" src="{% static "js/chronos/week_select.js" %}"></script>
+  {% endif %}
+
+  <div class="row no-margin">
+    <div class="col s8 m6 l8 xl9">
+      <h4>
+        {% trans "Timetable" %} <i>{{ el }}</i>
+      </h4>
+
+      {# Show class teacher and deputy class teacher #}
+      {% if type == "group" and el.owners.all %}
+        <h5>{% trans "Group teachers:" %}
+          {% for teacher in el.owners.all %}
+            <span data-position="bottom" class="tooltipped"
+                  data-tooltip="{{ teacher }}">
+                            <a href="{% url "timetable" "teacher" teacher.pk %}">
+                                {{ teacher.short_name }}</a></span>{% if not forloop.last %},{% endif %}
+          {% endfor %}
+        </h5>
+      {% endif %}
+    </div>
+    {# Show print button only if not on mobile #}
+    <div class="col s4 m6 l4 xl3 right align-right no-print">
+      <a class="waves-effect waves-teal btn-flat btn-flat-medium right hide-on-small-and-down" id="print">
+        <i class="material-icons center">print</i>
+      </a>
+    </div>
+  </div>
+  <div class="row">
+    {% if smart %}
+      {# Show if smart #}
+      {# Toggle button to regular and smart plan badge #}
+      <div class="row s12 m6 left">
+        <span class="badge new primary-color left smart-plan-badge">{% trans "SMART PLAN" %}</span>
+
+        <a class="waves-effect waves-light btn-flat no-print"
+           href="{% url "timetable_regular" type pk "regular" %}">
+          <i class="material-icons left">slideshow</i>
+          {% trans "Show regular timetable" %}
+        </a>
+      </div>
+
+      {# Week select #}
+      <div class="col s12 m6 right">
+        <div class="col s2 no-print">
+          <a class="waves-effect waves-teal btn-flat btn-flat-medium right" href="{{ url_prev }}">
+            <i class="material-icons center">navigate_before</i>
+          </a>
+        </div>
+
+        {% with wanted_week=week %}
+          <div class="input-field col s8 no-margin hide-on-med-and-up">
+            <select id="calendar-week-1">
+              {% for week in weeks %}
+                <option value="{{ week.week }}" {% if week == wanted_week %}
+                        selected {% endif %}>{% trans "CW" %} {{ week.week }} ({{ week.0|date:"SHORT_DATE_FORMAT" }}–{{ week.6|date:"SHORT_DATE_FORMAT" }})
+                </option>
+              {% endfor %}
+            </select>
+          </div>
+
+          <div class="input-field col s8 no-margin hide-on-med-and-down">
+            <select id="calendar-week-2">
+              {% for week in weeks %}
+                <option value="{{ week.week }}" {% if week == wanted_week %}
+                        selected {% endif %}>{% trans "CW" %} {{ week.week }} ({{ week.0|date:"j.n" }}–{{ week.6|date:"SHORT_DATE_FORMAT" }})
+                </option>
+              {% endfor %}
+            </select>
+          </div>
+
+          <div class="input-field col s8 no-margin hide-on-small-and-down hide-on-large-only">
+            <select id="calendar-week-3">
+              {% for week in weeks %}
+                <option value="{{ week.week }}" {% if week == wanted_week %}
+                        selected {% endif %}>{% trans "CW" %} {{ week.week }} ({{ week.0|date:"j.n" }}–{{ week.6|date:"j.n" }})
+                </option>
+              {% endfor %}
+            </select>
+          </div>
+        {% endwith %}
+
+        <div class="col s2 no-print">
+          <a class="waves-effect waves-teal btn-flat btn-flat-medium left" href="{{ url_next }}">
+            <i class="material-icons center">navigate_next</i>
+          </a>
+        </div>
+      </div>
+
+    {% else %}
+      {# Show if regular #}
+      <a class="waves-effect waves-light btn-flat no-print"
+         href="{% url "timetable" type pk %}">
+        <i class="material-icons left">slideshow</i>
+        {% trans "Show SMART PLAN" %}
+      </a>
+    {% endif %}
+  </div>
+
+  {#  {% include "chronos/hintsinplan.html" %}#}
+
+  {# show full timetable on tablets, laptops and pcs #}
+  <div class="timetable-plan hide-on-small-and-down">
+
+    {#  Week days #}
+    <div class="row">
+      <div class="col s2">
+
+      </div>
+      {# Show short weekdays on tablets #}
+      {% for day in weekdays_short.items %}
+        <div class="col s2 hide-on-large-only">
+          <div class="card timetable-title-card">
+            <div class="card-content">
+                            <span class="card-title">
+                                {{ day.1 }}
+                            </span>
+              {#              {% if day.1 %}#}
+              {#                <span class="badge new blue center-align holiday-badge">{{ day.1.0 }}</span>#}
+              {#              {% endif %}#}
+            </div>
+          </div>
+        </div>
+      {% endfor %}
+
+      {# Show long weekdays elsewere #}
+      {% for day in weekdays.items %}
+        <div class="col s2 hide-on-med-only">
+          <div class="card timetable-title-card">
+            <div class="card-content">
+                            <span class="card-title">
+                                {{ day.1 }}
+                            </span>
+              {#              {% if day.1 %}#}
+              {#                <span class="badge new blue center-align holiday-badge">{{ day.1.0 }}</span>#}
+              {#              {% endif %}#}
+            </div>
+          </div>
+        </div>
+      {% endfor %}
+    </div>
+
+    {#  Lessons #}
+    {% for period, lesson_periods_period in lesson_periods.items %}
+
+      <div class="row">
+        <div class="col s2">
+          {% include "chronos/partials/period_time.html" with period=period periods=periods %}
+        </div>
+
+        {% for weekday, lessons in lesson_periods_period.items %}
+          {# A lesson #}
+          <div class="col s2">
+            {% include "chronos/partials/lesson.html" with lessons=lessons %}
+          </div>
+        {% endfor %}
+      </div>
+    {% endfor %}
+  </div>
+
+  {# show 5 seperate ones on mobiles #}
+  <div class="timetable-plan hide-on-med-and-up">
+    {% for day in weekdays.items %}
+      <div class="card timetable-mobile-title-card">
+        <div class="card-content">
+                    <span class="card-title">
+                        {{ day.1 }}
+                    </span>
+          {#          {% if day.1 %}#}
+          {#            <span class="badge new blue center-align holiday-badge">{{ day.1.0 }}</span>#}
+          {#          {% endif %}#}
+          {#          &nbsp;#}
+        </div>
+      </div>
+      {% for period, lesson_periods_period in lesson_periods.items %}
+        <div class="row">
+          <div class="col s4">
+            {% include "chronos/partials/period_time.html" with period=period periods=periods %}
+          </div>
+
+          {% for weekday, lessons in lesson_periods_period.items %}
+            {% if forloop.counter0|add:"1" == day.0 %}
+              <div class="col s8">
+                {# A lesson #}
+                {% include "chronos/partials/lesson.html" with lessons=lessons %}
+              </div>
+            {% endif %}
+          {% endfor %}
+        </div>
+      {% endfor %}
+    {% endfor %}
+  </div>
+{% endblock %}
diff --git a/aleksis/apps/chronos/templates/chronos/tt_day.html b/aleksis/apps/chronos/templates/chronos/tt_day.html
deleted file mode 100644
index 203d8091f4cf65c3b3c65c4c3ec99b33951bb125..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/chronos/tt_day.html
+++ /dev/null
@@ -1,22 +0,0 @@
-{# -*- engine:django -*- #}
-
-<div class="col-sm px-0">
-  <div class="container">
-    <div class="row">
-      <div class="col-sm px-0">
-        <div class="card chronos-head">
-          <div class="card-body">
-            <span class="card-title">{{ weekday_name }}</span>
-          </div>
-        </div>
-      </div>
-    </div>
-    {% for period_num, lesson_period in lesson_periods.items %}
-      <div class="row">
-        <div class="col-sm px-0">
-          {% include "chronos/tt_lesson.html" with lesson_period=lesson_period %}
-        </div>
-      </div>
-    {% endfor %}
-  </div>
-</div>
diff --git a/aleksis/apps/chronos/templates/chronos/tt_lesson.html b/aleksis/apps/chronos/templates/chronos/tt_lesson.html
deleted file mode 100644
index 6627fb51963735d926f188c92933d32eab303715..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/chronos/tt_lesson.html
+++ /dev/null
@@ -1,46 +0,0 @@
-{# -*- engine:django -*- #}
-
-<div class="card chronos-lesson
-  {% if lesson_period.get_substitution.cancelled %}
-    border border-danger chronos-lesson-cancelled
-  {% elif lesson_period.get_substitution %}
-    border border-warning
-  {% endif %}
-  "
-  style="
-  {% if lesson_period.lesson.subject.colour_fg %}
-  color: {{ lesson_period.lesson.subject.colour_fg }};
-  {% endif %}
-  {% if lesson_period.lesson.subject.colour_bg %}
-  background-color: {{ lesson_period.lesson.subject.colour_bg }};
-  {% endif %}
-  ">
-  <div class="card-body">
-    <div class="row">
-      <div class="col-sm">
-        <span class="card-title">
-          {{ lesson_period.get_subject.abbrev }}
-        </span>
-      </div>
-    </div>
-    <div class="row">
-      <div class="col-sm">
-        {% for group in lesson_period.get_groups.all %}
-          <span class="card-text">{{ group.short_name }}</span>
-        {% endfor %}
-      </div>
-      <div class="col-sm">
-        {% for teacher in lesson_period.get_teachers.all %}
-          <a href="{% url 'person_by_id' teacher.id %}"
-            title="{{ teacher.first_name }} {{ teacher.last_name }}"
-            class="card-text">
-            {{ teacher.short_name }}
-          </a>
-        {% endfor %}
-      </div>
-      <div class="col-sm">
-        <span class="card-text">{{ lesson_period.get_room.short_name }}</span>
-      </div>
-    </div>
-  </div>
-</div>
diff --git a/aleksis/apps/chronos/templates/chronos/tt_week.html b/aleksis/apps/chronos/templates/chronos/tt_week.html
deleted file mode 100644
index d85c4bea6030f2a6cb8f72b23f0675d7581bce51..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/chronos/tt_week.html
+++ /dev/null
@@ -1,74 +0,0 @@
-{# -*- engine:django -*- #}
-
-{% extends "core/turnable.html" %}
-{% load bootstrap4 data_helpers i18n staticfiles %}
-
-{% block bootstrap4_extra_head %}
-  {{ block.super }}
-  <link rel="stylesheet" href="{% static 'css/chronos/timetable.css' %}" />
-  {{ select_form.media.css }}
-{% endblock %}
-
-{% block bootstrap4_extra_script %}
-  {{ block.super }}
-  {{ select_form.media.js }}
-{% endblock %}
-
-{% block bootstrap4_title %}{% blocktrans %}Timetable{% endblocktrans %} - {{ block.super }}{% endblock %}
-
-{% block current_content %}
-  <form method="get">
-    <ul id="timetable_select_form">
-      {{ select_form.as_ul }}
-    </ul>
-    <button type="submit" class="btn btn-dark">
-      {% blocktrans %}Select{% endblocktrans %}
-    </button>
-  </form>
-
-  <div class="row">
-    <div class="col-sm px-0">
-      <div class="container">
-        <div class="row">
-          <div class="col-sm px-0">
-            <div class="card chronos-head">
-              <div class="card-body">
-                <span class="card-title">{% blocktrans %}Times{% endblocktrans %}</span>
-              </div>
-            </div>
-          </div>
-        </div>
-        {% for num, times in periods.items %}
-          <div class="row">
-            <div class="col-sm px-0">
-              <div class="card chronos-lesson">
-                <div class="card-body">
-                  <div class="row">
-                    <div class="col-sm px-0">
-                      <span class="card-title">{{ num }}.</span>
-                    </div>
-                  </div>
-                  <div class="row">
-                    <div class="col-sm px-0">
-                      <span class="card-text">{{ times.0}}</span>
-                    </div>
-                    <div class="col-sm px-0">
-                      <span class="card-text">-</span>
-                    </div>
-                    <div class="col-sm px-0">
-                      <span class="card-text">{{ times.1 }}</span>
-                    </div>
-                  </div>
-                </div>
-              </div>
-            </div>
-          </div>
-        {% endfor %}
-      </div>
-    </div>
-
-    {% for weekday, lesson_periods_day in lesson_periods.items %}
-      {% include "chronos/tt_day.html" with weekday_name=weekdays|get_dict:weekday lesson_periods=lesson_periods_day %}
-    {% endfor %}
-  </div>
-{% endblock %}
diff --git a/aleksis/apps/chronos/templates/timetable/all.html b/aleksis/apps/chronos/templates/timetable/all.html
deleted file mode 100644
index ce5cc999c6fa461bbb9456c90a97b5f9d7294423..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/timetable/all.html
+++ /dev/null
@@ -1,52 +0,0 @@
-{% include 'partials/header.html' %}
-
-<main>
-    <h3>Alle Pläne</h3>
-    <div class="row">
-        <div class="col s12 m4">
-            <h4>Lehrkräfte</h4>
-            <ul class="collection">
-                {% for teacher in teachers %}
-                    <li class="collection-item avatar">
-                        <i class="circle">{{ teacher.shortcode }}</i><!-- Shortcode -->
-                        <a href="{% url 'timetable_smart_plan' 'teacher' teacher.id %}">{{ teacher.first_name }}
-                            <strong>{{ teacher.name }}</strong></a>
-                    </li>
-                {% endfor %}
-            </ul>
-        </div>
-
-        <div class="col s12 m4">
-            <h4>Klassen</h4>
-            <ul class="collection">
-                {% for class in classes %}
-                    <li class="collection-item avatar">
-                        <i class="circle">{{ class.name }}</i>
-                        <a href="{% url 'timetable_smart_plan' 'class' class.id %}"><strong>{{ class.name }}</strong></a>
-                        <p>
-                            {{ class.text1|default:"" }} – {{ class.text2|default:"" }} <br>
-                            Raum: {{ class.room.name|default:"---" }}
-                        </p>
-                    </li>
-                {% endfor %}
-            </ul>
-        </div>
-
-        <div class="col s12 m4">
-            <h4>Räume</h4>
-            <ul class="collection">
-                {% for room in rooms %}
-                    <li class="collection-item avatar">
-                        <i class="circle">{{ room.shortcode }}</i>
-                        <a href="{% url 'timetable_smart_plan' 'room' room.id %}"><strong>{{ room.name }}</strong></a>
-                    </li>
-                {% endfor %}
-            </ul>
-        </div>
-
-
-    </div>
-
-</main>
-
-{% include 'partials/footer.html' %}
diff --git a/aleksis/apps/chronos/templates/timetable/datepicker.html b/aleksis/apps/chronos/templates/timetable/datepicker.html
deleted file mode 100644
index 56fd84d04da8dcecd13cae3cc10342682f2582ed..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/timetable/datepicker.html
+++ /dev/null
@@ -1,81 +0,0 @@
-<script type="text/javascript">
-    function updateDatepicker() {
-        {% if not display_date_only %}
-            $("#date").val(formatDate(activeDate));
-        {% endif %}
-    }
-
-    function update() {
-        console.log("Render new.");
-
-        updateDatepicker();
-    }
-
-    function loadNew() {
-        window.location.href = dest + formatDateForDjango(activeDate);
-    }
-
-    function onDateBeforeClick() {
-        if (activeDate.getDay() === 1) {
-            var minus = 3;
-        } else {
-            var minus = 1;
-        }
-        activeDate.setDate(activeDate.getDate() - minus);
-        update();
-        loadNew();
-    }
-
-    function onDateNextClick() {
-        if (activeDate.getDay() === 5) {
-            var plus = 3;
-        } else {
-            var plus = 1;
-        }
-        activeDate.setDate(activeDate.getDate() + plus);
-        update();
-        loadNew();
-    }
-
-    function onDateChanged() {
-        var str = $("#date").val();
-        var split = str.split(".")
-        activeDate = new Date(split[2], split[1] - 1, split[0]);
-        update();
-        loadNew();
-    }
-
-    var activeDate = new Date({{ date_js }});
-
-    $(document).ready(function () {
-        $("#date-before").click(onDateBeforeClick);
-        $("#date-next").click(onDateNextClick);
-        $("#date").change(onDateChanged);
-
-        update();
-    })
-</script>
-
-
-<div class="col s2" style="display: initial;">
-    <a class="waves-effect waves-teal btn-flat btn-flat-medium left" id="date-before">
-        <i class="material-icons center">navigate_before</i>
-    </a>
-
-</div>
-{% if display_date_only %}
-    <div class="col s8">
-    <span class="card-title center-block" id="date">
-        {{ date|date:"l, j.n.Y" }}
-    </span>
-    </div>
-{% else %}
-    <div class="col s8">
-        <input type="text" class="datepicker center-align" id="date">
-    </div>
-{% endif %}
-<div class="col s2" style="display: initial;">
-    <a class="waves-effect waves-teal btn-flat btn-flat-medium right" id="date-next">
-        <i class="material-icons center">navigate_next</i>
-    </a>
-</div>
diff --git a/aleksis/apps/chronos/templates/timetable/fallback.html b/aleksis/apps/chronos/templates/timetable/fallback.html
deleted file mode 100644
index b68dbeed2525673e4f40f2daa369c08280054ef2..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/timetable/fallback.html
+++ /dev/null
@@ -1,8 +0,0 @@
-{% include 'partials/header.html' %}
-
-<main>
-    <h3>Die Stundenpläne sind aktuell noch nicht einsehbar.</h3>
-
-</main>
-
-{% include 'partials/footer.html' %}
diff --git a/aleksis/apps/chronos/templates/timetable/latex/header.tex b/aleksis/apps/chronos/templates/timetable/latex/header.tex
deleted file mode 100644
index 1f80f9705ebe19e66fa906ece98adeafd577b666..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/timetable/latex/header.tex
+++ /dev/null
@@ -1,63 +0,0 @@
-\documentclass[11pt]{article}
-\usepackage[ngerman]{babel}
-\usepackage[sfdefault]{cabin}
-\usepackage[utf8]{inputenc}
-\usepackage[a4paper,left=1cm,right=1cm,top=2cm,bottom=2.8cm,bindingoffset=0mm]{geometry}
-
-% Packages
-\usepackage{fancyhdr}
-\usepackage{lastpage}
-\usepackage{graphicx}
-\usepackage{longtable}
-\usepackage{booktabs}
-\usepackage{multirow}
-\usepackage{color, colortbl}
-\usepackage[colorlinks, linkcolor = black, citecolor = black, filecolor = black, urlcolor = black]{hyperref}
-
-\usepackage{ulem, xpatch}
-\xpatchcmd{\sout}
-{\bgroup}
-{\bgroup\def\ULthickness{1.5pt}}
-{}{}
-
-% Badge box
-\usepackage{tcolorbox}
-\newtcbox{\badge}{nobeforeafter,colframe=green,colback=green,boxrule=0.5pt,arc=4pt,
-boxsep=0pt,left=4pt,right=4pt,top=4pt,bottom=4pt,tcbox raise base,
-grow to left by=0pt,
-grow to right by=-3pt,
-enlarge top by=3pt,
-enlarge bottom by=3pt,coltext=white}
-
-% Define colors
-\definecolor{ grey }{RGB}{208, 208, 208}
-\definecolor{ darkgrey }{rgb}{0.6,0.6,0.6}
-\definecolor{ white }{rgb}{1,1,1}
-\definecolor{ green }{RGB}{76,175,80}
-\definecolor{green}{RGB}{76,175,80}
-\definecolor{ blue }{RGB}{41,7,249}
-\definecolor{ black }{RGB}{0,0,0}
-\definecolor{ purple }{RGB}{156, 39, 176}
-
-% Define header
-\pagestyle{fancy}
-
-% Left header: logo
-\lhead{\includegraphics[width=5cm]{% templatetag openbrace %}{{LOGO_FILENAME}}{% templatetag closebrace %}}
-
-% Define footer
-\lfoot{Katharineum zu Lübeck}
-\cfoot{\thepage}%\ von \pageref{LastPage}}
-\rfoot{\small Umsetzung: © 2018--2019 by Computer-AG}
-\rhead{\textbf{
-Vertretungen }\\
-Stand: {% now "j. F Y H:i" %}\\
-}
-
-% Define own commands
-%% tightlist from pandoc is missing in default.latex
-%% see https://tex.stackexchange.com/questions/257418/error-tightlist-converting-md-file-into-pdf-using-pandoc
-\providecommand{\tightlist}{%
-  \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
-
-\begin{document}
diff --git a/aleksis/apps/chronos/templates/timetable/latex/hints.tex b/aleksis/apps/chronos/templates/timetable/latex/hints.tex
deleted file mode 100644
index 6077fd4adf1648c135c01181d3f09628be414793..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/timetable/latex/hints.tex
+++ /dev/null
@@ -1,15 +0,0 @@
-{% load martortags %}
-{% if hints %}
-\subsection*{\hspace{0.7em}Hinweise}
-\vspace{-0.7em}
-\begin{itemize}
-    \setlength\itemsep{0.1em}
-    {% for hint in hints %}
-    \normalsize
-    \item \small
-    {{ hint.classes_formatted }}{% if hint.teachers and hint.classes.all %}, {% endif %}{% if hint.teachers %}Lehrkräfte{% endif %}:
-    \normalsize
-{{ hint.text_as_latex|safe }}
-{% endfor %}
-\end{itemize}
-{% endif %}
diff --git a/aleksis/apps/chronos/templates/timetable/latex/room.tex b/aleksis/apps/chronos/templates/timetable/latex/room.tex
deleted file mode 100644
index 7b9b5678487b54271fce13bf31195b24e36f8709..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/timetable/latex/room.tex
+++ /dev/null
@@ -1,15 +0,0 @@
-{% if not sub.is_event %}{% if sub.sub.type == 3 %}
-{{ sub.sub.corridor.name }}
-{% elif sub.sub.type == 1 or sub.sub.type == 2 %}
-{% elif sub.sub.room_new and sub.sub.room_old %}
-\sout{% templatetag openbrace %}{{ sub.sub.room_old.shortcode }}}
-$\rightarrow$
-{{ sub.sub.room_new.shortcode }}
-{% elif sub.sub.room_new and not sub.sub.room_old %}
-{{ sub.sub.room_new.shortcode }}
-{% elif not sub.sub.room_new and not sub.sub.room_old %}
-{% else %}
-{{ sub.sub.room_old.shortcode }}
-{% endif %}{% else %}
-{% for room in sub.rooms %}{{ room.shortcode }}{% if not forloop.last %}, {% endif %}{% endfor %}
-{% endif %}
diff --git a/aleksis/apps/chronos/templates/timetable/latex/subject.tex b/aleksis/apps/chronos/templates/timetable/latex/subject.tex
deleted file mode 100644
index 96b9d061a792a018cfd86ae5d8f9c78045399aa4..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/timetable/latex/subject.tex
+++ /dev/null
@@ -1,14 +0,0 @@
-{% if sub.is_event %}
-Veranstaltung
-{% elif sub.sub.type == 3 %}
-Aufsicht
-{% elif not sub.sub.subject_new and not sub.sub.subject_old %}
-{% elif sub.sub.type == 1 or sub.sub.type == 2 %}
-\sout{% templatetag openbrace %}{{ sub.sub.subject_old.shortcode }}}
-{% elif sub.sub.subject_new and sub.sub.subject_old %}
-\sout{% templatetag openbrace %}{{ sub.sub.subject_old.shortcode }}} $\rightarrow$ \textbf { {{ sub.sub.subject_new.shortcode }} }
-{% elif sub.sub.subject_new and not sub.sub.subject_old %}
-{{ sub.sub.subject_new.shortcode }}
-{% else %}
-{{ sub.sub.subject_old.shortcode }}
-{% endif %}
diff --git a/aleksis/apps/chronos/templates/timetable/latex/substitutions.tex b/aleksis/apps/chronos/templates/timetable/latex/substitutions.tex
deleted file mode 100644
index 2b3d21e35170597ca04506b5e6483604764b737d..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/timetable/latex/substitutions.tex
+++ /dev/null
@@ -1,50 +0,0 @@
-{% load common %}
-{% load tex %}
-
-\large
-\subsubsection*{}
-
-\section*{\Huge Vertretungen {{ date|date:"l, j. F Y"}}}
-
-{%  include "timetable/latex/hints.tex" %}
-
-{% if header_info.is_box_needed %}
-\begin{tabular}{@{\hspace{-1em}}p{0.22\linewidth}p{0.73\linewidth}}
-{% for row in header_info.rows %}
-    \textbf{ {{ row.0 }} } & {{ row.1 }} \\
-{% endfor %}
-\end{tabular}
-{% endif %}
-
-% Init table
-{% set color_background = 1 %}
-{% set last_classes = "" %}
-
-\def\arraystretch{1.1}
-\begin{longtable}{p{20mm}p{10mm}p{30mm}p{25mm}p{30mm}p{45mm}}
-    \textbf{Klassen} & \textbf{Std.} & \textbf{Lehrer} & \textbf{Fach} & \textbf{Raum} & \textbf{Hinweis}\\\hline
-    \endhead
-    {% for sub in subs %}
-        {#  Color groups of classes in grey/white #}
-        {% if last_classes != sub.classes %}
-            {% if color_background %}{% set color_background = 0 %}
-            {% else %}{% set color_background = 1 %}
-            {% endif %}
-        {% endif %}
-        {% set last_classes = sub.classes %}
-        {# Background color #}
-        {% if color_background %}\rowcolor{ grey }{% endif %}
-        {% with c=sub.color %}
-            {#  Display classes #}
-            \color{ {{c}} }\textbf{ {{ sub.classes }} } &
-            {# Display lesson number #}
-            \color{ {{c}} } {{ sub.lesson }} &
-            \color{ {{c}} } {% include "timetable/latex/teacher.tex" %} &
-            \color{ {{c}} } {% include "timetable/latex/subject.tex" %} &
-            \color{ {{c}} } {% include "timetable/latex/room.tex" %} &
-            {# Display badge (for cancellations) #}     {# Display notice and new line #}
-            {% if sub.badge %} \footnotesize\badge{ {{ sub.badge }} } {% endif %}
-            \color{ {{c}} } \large\textit{ {{sub.text|default:""|safe|texify|safe}} } \\
-        {% endwith %}
-    {% endfor %}
-\end{longtable}
diff --git a/aleksis/apps/chronos/templates/timetable/latex/teacher.tex b/aleksis/apps/chronos/templates/timetable/latex/teacher.tex
deleted file mode 100644
index 5320e06994ce99db3671e74c078a2fe6cb0e768f..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/timetable/latex/teacher.tex
+++ /dev/null
@@ -1,13 +0,0 @@
-{% if not sub.is_event %}{% if sub.sub.type == 1 %}
-\sout{% templatetag openbrace %}{{ sub.sub.teacher_old.shortcode }}}
-{% elif sub.sub.teacher_new and sub.sub.teacher_old %}
-\sout{% templatetag openbrace %}{{ sub.sub.teacher_old.shortcode }}}
-$\rightarrow$
-{{ sub.sub.teacher_new.shortcode }}
-{% elif sub.sub.teacher_new and not sub.sub.teacher_old %}
-{{ sub.sub.teacher_new.shortcode }}
-{% elif sub.sub.teacher_old %}
-{{ sub.sub.teacher_old.shortcode }}
-{% endif %}{% else %}
-{% for teacher in sub.teachers %}{{ teacher.shortcode }}{% if not forloop.last %}, {% endif %}{% endfor %}
-{% endif %}
diff --git a/aleksis/apps/chronos/templates/timetable/lesson.html b/aleksis/apps/chronos/templates/timetable/lesson.html
deleted file mode 100644
index 5b2cca1c6a196d4e90e9e784c39d9569d30d78b3..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/timetable/lesson.html
+++ /dev/null
@@ -1,141 +0,0 @@
-<div class="card lesson-card">
-    <div class="card-content">
-
-        {# Every element of the lesson #}
-        {% for element_container in col.elements %}
-            <div style="
-
-                    {# Display background color only if no badge exists and it is not the old room and there are no holidays #}
-                    {% if not element_container.substitution.table.badge %}
-                        {% if not element_container.is_old or type != 1 %}
-                            {% if not element_container.is_hol %}
-                                background-color: {{ element_container.element.subject.hex_color }};
-                            {% endif %}
-                        {% endif %}
-                    {% endif %}"
-
-                    {# Add CSS class for sub when it's a sub #}
-                 class="{% if element_container.substitution %}{% if element_container.substitution.table.is_event %}lesson-with-event{% else %}lesson-with-sub{% endif %}{% endif %}">
-                <p>
-                    {% if element_container.is_hol %}
-
-                        {# <p><strong>{ element_container.element.holiday_reason }}</strong></p>span class="badge new blue darken-2">Schulfrei</span>#}
-
-                    {% elif element_container.substitution %}
-                        {# SUBSTITUTION #}
-                        {% if type == 1 and element_container.is_old %}
-                            {# When it's the old room, let it empty #}
-
-                        {% elif element_container.substitution.table.badge %}
-                            {# When a badge (cancellation, etc.) exists, then display it with the teacher#}
-
-                            {# Class or room > Display teacher #}
-                            {% if type == 2 or type == 1 %}
-                                {% if element_container.element.teacher %}
-                                    <span data-position="bottom" class="tooltipped"
-                                          data-tooltip="{{ element_container.element.teacher }}">
-                                        <a
-                                                href="{% url "timetable_smart_plan" "teacher" element_container.element.teacher.id %}">{{ element_container.element.teacher.shortcode }}</a>
-                                    </span>
-                                    <br>
-                                {% endif %}
-                            {% endif %}
-
-                            {# Badge #}
-                            <span class="badge new green darken-2">{{ element_container.substitution.table.badge }}</span>
-
-
-
-                        {% else %}
-                            {# Display sub #}
-
-                            {% with sub=element_container.substitution.table %}
-                                {# Teacher or room > display classes #}
-                                {% if type == 0 or type == 1 %}
-                                    {{ element_container.substitution.table.classes }}
-                                {% endif %}
-
-                                {# Display teacher with tooltip #}
-                                {% include "timetable/subs/teacher.html" %}
-
-                                {# Display subject #}
-                                {% include "timetable/subs/subject.html" %}
-
-                                {# Teacher or class > display room #}
-                                {% if type == 0 or type == 2 %}
-                                    {% include "timetable/subs/room.html" %}
-                                {% endif %}
-                            {% endwith %}
-                        {% endif %}
-
-                        {# When it isn't a room or the old plan, then display the extra text (e. g. work orders) AND NOT A EVENT#}
-                        {% if not   element_container.substitution.table.is_event %}
-                            {% if not type == 1  or not element_container.is_old %}
-                                <br>
-                                <small>
-                                    <em>{{ element_container.substitution.table.text|default:"" }}</em>
-                                </small>
-                            {% endif %}
-                        {% endif %}
-                        {# Display the extra text for events #}
-                        {% if element_container.substitution.table.is_event %}
-                            {% if type == 0 and element_container.substitution.table.classes == "" and element_container.substitution.table.rooms|length == 0 and element_container.substitutions.table.teachers|length == 0 %}
-                                <em>{{ element_container.substitution.table.text|default:"" }}</em>
-                            {% elif type == 2 and  element_container.substitution.table.teachers|length == 0  and  element_container.substitution.table.rooms|length == 0 %}
-                                <em>{{ element_container.substitution.table.text|default:"" }}</em>
-                            {% elif type == 1  and  element_container.substitution.table.teachers|length == 0 and element_container.substitution.table.classes == "" %}
-                                <em>{{ element_container.substitution.table.text|default:"" }}</em>
-                            {% else %}
-                                <br>
-                                <small>
-                                    <em>{{ element_container.substitution.table.text|default:"" }}</em>
-                                </small>
-                            {% endif %}
-                        {% endif %}
-
-                    {% else %}
-                        {# Normal plan #}
-
-                        {# Teacher or room > Display classes #}
-                        {% if type == 0 or type == 1 %}
-                            {#                            {{ element_container.element.classes }}#}
-                            {% if element_container.element.classes %}
-                                <a href="{% url "timetable_smart_plan" "class" element_container.element.classes.0.id %}">
-                                    {{ element_container.classes_formatted }}
-                                </a>
-                            {% endif %}
-                        {% endif %}
-
-                        {# Class or room > Display teacher #}
-                        {% if type == 2 or type == 1 %}
-                            {% if element_container.element.teacher %}
-                                <span data-position="bottom" class="tooltipped"
-                                      data-tooltip="{{ element_container.element.teacher }}">
-                                    <a href="{% url "timetable_smart_plan" "teacher" element_container.element.teacher.id %}">
-                                        {{ element_container.element.teacher.shortcode }}
-                                    </a>
-                                </span>
-                            {% endif %}
-                        {% endif %}
-
-                        {# Display subject #}
-                        <strong>{{ element_container.element.subject.shortcode }}</strong>
-
-                        {# Teacher or class > Display room #}
-                        {% if type == 0 or type == 2 %}
-                            <span class="tooltipped" data-position="bottom"
-                                  data-tooltip="{{ element_container.room.name }}">
-                                {% if element_container.room %}
-                                    <a href="{% url "timetable_smart_plan" "room" element_container.room.id %}">
-                                        {{ element_container.room.shortcode }}
-                                    </a>
-                                {% endif %}
-                            </span>
-                        {% endif %}
-                    {% endif %}
-                </p>
-            </div>
-
-        {% endfor %}
-    </div>
-</div>
diff --git a/aleksis/apps/chronos/templates/timetable/myplan.html b/aleksis/apps/chronos/templates/timetable/myplan.html
deleted file mode 100644
index 49385ff63350268bb81d24b31f0671580747e803..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/timetable/myplan.html
+++ /dev/null
@@ -1,82 +0,0 @@
-{% include 'partials/header.html' %}
-
-
-<main>
-    <div class="row nomargin">
-        <div class="col m12 s12 l6">
-            <h4>
-                Mein Plan <i>{{ el }}</i>
-                <span class="badge new primary-color ">SMART PLAN</span>
-            </h4>
-            <a class="btn-flat waves-effect waves-light" href="{% url "timetable_smart_plan"  raw_type id %}">Wochenplan
-                anzeigen</a>
-        </div>
-    </div>
-
-    <div class="row nomargin">
-        <div class="col m12 s12 l6">
-            {% include "timetable/hintsinplan.html" %}
-        </div>
-    </div>
-
-    <script type="text/javascript">
-        var dest = "/timetable/my/";
-    </script>
-
-    <div class="row">
-        <div class="timetable-plan col s12 m12 l6">
-
-            {#  Date #}
-
-            <div class="row">
-                <div class="col s12">
-                    <div class="card timetable-title-card">
-                        <div class="card-content">
-                    <span class="card-title">
-                        {% include "timetable/datepicker.html" %}
-                        {% if holiday %}
-                            <span class="badge new blue center-align holiday-badge">{{ holiday.0 }}</span>
-                        {% endif %}
-                    </span>
-                        </div>
-                    </div>
-
-                </div>
-            </div>
-            {#  Lessons #}
-            {% for row, time in plan %}
-                <div class="row">
-                    <div class="col s4">
-                        <div class="card timetable-title-card">
-                            <div class="card-content">
-
-                                {# Lesson number #}
-                                <span class="card-title left">
-                                {{ time.number_format }}
-                             </span>
-
-                                {# Time dimension of lesson #}
-                                <div class="right timetable-time grey-text text-darken-2">
-                                    <span>{{ time.start|date:"H:i" }}</span><br>
-                                    <span>{{ time.end|date:"H:i" }}</span>
-                                </div>
-                            </div>
-                        </div>
-
-                    </div>
-                    {% for col in row %}
-                        {% if forloop.counter0 == week_day %}
-                            <div class="col s8">
-                                {# A lesson #}
-                                {% include "timetable/lesson.html" %}
-                            </div>
-                        {% endif %}
-                    {% endfor %}
-                </div>
-            {% endfor %}
-
-        </div>
-    </div>
-</main>
-
-{% include 'partials/footer.html' %}
diff --git a/aleksis/apps/chronos/templates/timetable/plan.html b/aleksis/apps/chronos/templates/timetable/plan.html
deleted file mode 100644
index 88e6e30a42cc90d3546bbe256f115a9e3d6f43f5..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/timetable/plan.html
+++ /dev/null
@@ -1,262 +0,0 @@
-{% include 'partials/header.html' %}
-{% load copy_filter %}
-<script type="text/javascript">
-    {% if smart %}
-        var week = {{ selected_week }};
-        var year = {{ selected_year }};
-        function goToCalendarWeek(cw, year) {
-            window.location.href = "{% url "timetable_smart_plan" raw_type id %}/" + year + "/" + cw;
-        }
-        function onCalendarWeekChanged(where) {
-            goToCalendarWeek($(where).val(), year);
-        }
-
-        function weekBefore() {
-            if (week > 1) {
-                goToCalendarWeek(week - 1, year)
-            } else {
-                goToCalendarWeek(52, year - 1)
-            }
-        }
-
-        function weekNext() {
-            if (week < 52) {
-                goToCalendarWeek(week + 1, year);
-            } else {
-                goToCalendarWeek(1, year + 1);
-            }
-        }
-
-        $(document).ready(function () {
-            $("#calendar-week-1").change(function () {
-                onCalendarWeekChanged("#calendar-week-1");
-            });
-            $("#calendar-week-2").change(function () {
-                onCalendarWeekChanged("#calendar-week-2");
-            });
-            $("#calendar-week-3").change(function () {
-                onCalendarWeekChanged("#calendar-week-3");
-            });
-            $("#week-before").click(weekBefore);
-            $("#week-next").click(weekNext);
-        });
-    {% endif %}
-</script>
-<main>
-    <div class="row no-margin">
-        <div class="col s8 m6 l8 xl9">
-            <h3>
-                Stundenplan <i>{{ el }}</i>
-            </h3>
-
-            {# Show class teacher and deputy class teacher #}
-            {% if type == 2 and el.teachers %}
-                <h5>Klassenlehrkräfte:
-                    {% for teacher in el.teachers %}
-
-                        <span data-position="bottom" class="tooltipped"
-                              data-tooltip="{{ teacher }}">
-                            <a href="{% url "timetable_smart_plan" "teacher" teacher.id %}">
-                                {{ teacher.shortcode }}</a></span>{% if not forloop.last %},{% endif %}
-                    {% endfor %}
-                </h5>
-            {% endif %}
-        </div>
-        {# Show print button only if not on mobile #}
-        <div class="col s4 m6 l4 xl3 right align-right no-print">
-            <a class="waves-effect waves-teal btn-flat btn-flat-medium right hide-on-small-and-down" id="print">
-                <i class="material-icons center">print</i>
-            </a>
-        </div>
-    </div>
-    <div class="row">
-        {% if smart %}
-            {# Show if smart #}
-            {# Toggle button to regular and smart plan badge #}
-            <div class="row s12 m6 left">
-                <span class="badge new primary-color left smart-plan-badge">SMART PLAN</span>
-
-                <a class="waves-effect waves-light btn-flat no-print" style="padding-left: 3px; padding-right: 3px;"
-                   href="{% url "timetable_regular_plan" raw_type id "regular" %}">
-                    <i class="material-icons left">slideshow</i>
-                    REGELPLAN ANZEIGEN
-                </a>
-            </div>
-
-            {# Week select #}
-            <div class="col s12 m6 right">
-                <div class="col s2 no-print">
-                    <a class="waves-effect waves-teal btn-flat btn-flat-medium right" id="week-before">
-                        <i class="material-icons center">navigate_before</i>
-                    </a>
-                </div>
-                <div class="input-field col s8 no-margin hide-on-med-and-up">
-                    <select id="calendar-week-1">
-                        {% for week in weeks %}
-                            <option value="{{ week.calendar_week }}" {% if week.calendar_week == selected_week %}
-                                    selected {% endif %}> KW {{ week.calendar_week }}
-                                ({{ week.first_day|date:"j.n" }}–{{ week.last_day|date:"j.n" }})
-                            </option>
-                        {% endfor %}
-                    </select>
-                </div>
-                <div class="input-field col s8 no-margin hide-on-med-and-down">
-                    <select id="calendar-week-2">
-                        {% for week in weeks %}
-                            <option value="{{ week.calendar_week }}" {% if week.calendar_week == selected_week %}
-                                    selected {% endif %}> KW {{ week.calendar_week }} ({{ week.first_day|date:"j.n.Y" }}–{{ week.last_day|date:"j.n.Y" }})
-                            </option>
-                        {% endfor %}
-                    </select>
-                </div>
-                <div class="input-field col s8 no-margin hide-on-small-and-down hide-on-large-only">
-                    <select id="calendar-week-3">
-                        {% for week in weeks %}
-                            <option value="{{ week.calendar_week }}" {% if week.calendar_week == selected_week %}
-                                    selected {% endif %}> KW {{ week.calendar_week }}
-                                ({{ week.first_day|date:"j.n" }}–{{ week.last_day|date:"j.n.Y" }})
-                            </option>
-                        {% endfor %}
-                    </select>
-                </div>
-                <div class="col s2 no-print">
-                    <a class="waves-effect waves-teal btn-flat btn-flat-medium left" id="week-next">
-                        <i class="material-icons center">navigate_next</i>
-                    </a>
-                </div>
-            </div>
-
-        {% else %}
-            {# Show if regular #}
-            <a class="waves-effect waves-light btn-flat no-print"
-               href="{% url "timetable_smart_plan" raw_type id %}">
-                <i class="material-icons left">slideshow</i>
-                SMART PLAN ANZEIGEN
-            </a>
-        {% endif %}
-    </div>
-
-    {% include "timetable/hintsinplan.html" %}
-
-    {# show full timetable on tablets, laptops and pcs #}
-    <div class="timetable-plan hide-on-small-and-down">
-
-        {#  Week days #}
-        <div class="row">
-            <div class="col s2">
-
-            </div>
-            {# Show short weekdays on tablets #}
-            {% for day in short_week_days|deepcopy %}
-                <div class="col s2 hide-on-large-only">
-                    <div class="card timetable-title-card">
-                        <div class="card-content">
-                            <span class="card-title">
-                                {{ day.0 }}
-                            </span>
-                            {% if day.1 %}
-                                <span class="badge new blue center-align holiday-badge">{{ day.1.0 }}</span>
-                            {% endif %}
-                        </div>
-                    </div>
-                </div>
-            {% endfor %}
-            {# Show long weekdays elsewere #}
-            {% for day in long_week_days|deepcopy %}
-                <div class="col s2 hide-on-med-only">
-                    <div class="card timetable-title-card">
-                        <div class="card-content">
-                            <span class="card-title">
-                                {{ day.0.0 }}
-                            </span>
-                            {% if day.1 %}
-                                <span class="badge new blue center-align holiday-badge">{{ day.1.0 }}</span>
-                            {% endif %}
-                        </div>
-                    </div>
-                </div>
-            {% endfor %}
-        </div>
-
-        {#  Lessons #}
-        {% for row, time in plan|deepcopy %}
-            <div class="row">
-                <div class="col s2">
-                    <div class="card timetable-title-card">
-                        <div class="card-content">
-
-                            {# Lesson number #}
-                            <span class="card-title left">
-                                {{ time.number_format }}
-                            </span>
-
-                            {# Time dimension of lesson #}
-                            <div class="right timetable-time grey-text text-darken-2">
-                                <span>{{ time.start|date:"H:i" }}</span>
-                                <br>
-                                <span>{{ time.end|date:"H:i" }}</span>
-                            </div>
-                        </div>
-                    </div>
-
-                </div>
-                {% for col in row %}
-                    {# A lesson #}
-                    <div class="col s2">
-                        {% include "timetable/lesson.html" %}
-                    </div>
-                {% endfor %}
-            </div>
-        {% endfor %}
-    </div>
-
-    {# show 5 seperate ones on mobiles #}
-    <div class="timetable-plan hide-on-med-and-up">
-        {% for day in long_week_days|deepcopy %}
-            <div class="card timetable-mobile-title-card">
-                <div class="card-content">
-                    <span class="card-title">
-                        {{ day.0.0 }}
-                    </span>
-                    {% if day.1 %}
-                        <span class="badge new blue center-align holiday-badge">{{ day.1.0 }}</span>
-                    {% endif %}
-                    &nbsp;
-                </div>
-            </div>
-            {% for row, time in plan|deepcopy %}
-                <div class="row">
-                    <div class="col s4">
-                        <div class="card timetable-title-card">
-                            <div class="card-content">
-
-                                {# Lesson number #}
-                                <span class="card-title left">
-                                    {{ time.number_format }}
-                                </span>
-
-                                {# Time dimension of lesson #}
-                                <div class="right timetable-time grey-text text-darken-2">
-                                    <span>{{ time.start|date:"H:i" }}</span>
-                                    <br>
-                                    <span>{{ time.end|date:"H:i" }}</span>
-                                </div>
-                            </div>
-                        </div>
-
-                    </div>
-                    {% for col in row|deepcopy %}
-                        {% if forloop.counter0 == day.0.1 %}
-                            <div class="col s8">
-                                {# A lesson #}
-                                {% include "timetable/lesson.html" %}
-                            </div>
-                        {% endif %}
-                    {% endfor %}
-                </div>
-            {% endfor %}
-        {% endfor %}
-    </div>
-</main>
-
-{% include 'partials/footer.html' %}
diff --git a/aleksis/apps/chronos/templates/timetable/quicklaunch.html b/aleksis/apps/chronos/templates/timetable/quicklaunch.html
deleted file mode 100644
index 2647f44c697ec19ce5c05bd8d08ebeda22b14446..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/timetable/quicklaunch.html
+++ /dev/null
@@ -1,43 +0,0 @@
-{% include 'partials/header.html' %}
-
-<main>
-    <h4>Alle Pläne</h4>
-    <div class="row">
-        <div class="col s12 m4">
-            <h5>Lehrkräfte</h5>
-            {% for teacher in teachers %}
-                <a class="waves-effect waves-light btn btn-timetable-quicklaunch"
-                   href="{% url 'timetable_smart_plan' 'teacher' teacher.id %}">
-                    {{ teacher.shortcode }}
-                </a><!-- Shortcode -->
-            {% endfor %}
-        </div>
-
-        <div class="col s12 m4">
-            <h5>Klassen</h5>
-
-            {% for class in classes %}
-                <a class="waves-effect waves-light btn btn-timetable-quicklaunch"
-                   href="{% url 'timetable_smart_plan' 'class' class.id %}">
-                    {{ class.name }}
-                </a>
-            {% endfor %}
-
-        </div>
-
-        <div class="col s12 m4">
-            <h5>Räume</h5>
-            {% for room in rooms %}
-                <a class="waves-effect waves-light btn btn-timetable-quicklaunch"
-                   href="{% url 'timetable_smart_plan' 'room' room.id %}">
-                    {{ room.shortcode }}
-                </a>
-            {% endfor %}
-        </div>
-
-
-    </div>
-
-</main>
-
-{% include 'partials/footer.html' %}
diff --git a/aleksis/apps/chronos/templates/timetable/subs/room.html b/aleksis/apps/chronos/templates/timetable/subs/room.html
deleted file mode 100644
index 0b9aa41a5f875ea222bbed39fd875e7ba34c88ed..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/timetable/subs/room.html
+++ /dev/null
@@ -1,47 +0,0 @@
-{% if not sub.is_event %}
-    {% if sub.sub.type == 3 %}
-        {# Supervisement #}
-        {{ sub.sub.corridor.name }}
-    {% elif sub.sub.type == 1 or sub.sub.type == 2 %}
-        {# Canceled lesson: no room #}
-    {% elif sub.sub.room_new and sub.sub.room_old %}
-        {# New and old room available #}
-        <span class="tooltipped" data-position="bottom"
-              data-tooltip="{{ sub.sub.room_old.name }} → {{ sub.sub.room_new.name }}">
-            <a href="{% url "timetable_smart_plan" "room" sub.sub.room_old.id %}">
-                <s>{{ sub.sub.room_old.shortcode }}</s>
-            </a>
-            →
-            <a href="{% url "timetable_smart_plan" "room" sub.sub.room_new.id %}">
-                <strong>{{ sub.sub.room_new.shortcode }}</strong>
-            </a>
-        </span>
-    {% elif sub.sub.room_new and not sub.sub.room_old %}
-        {# Only new room available #}
-        <span class="tooltipped" data-position="bottom"
-              data-tooltip="{{ sub.sub.room_new.name }}">
-            <a href="{% url "timetable_smart_plan" "room" sub.sub.room_new.id %}">
-                {{ sub.sub.room_new.shortcode }}
-            </a>
-        </span>
-    {% elif not sub.sub.room_new and not sub.sub.room_old %}
-        {# Nothing to view #}
-    {% else %}
-        {# Only old room available #}
-        <span class="tooltipped" data-position="bottom"
-              data-tooltip="{{ sub.sub.room_old.name }}">
-            <a href="{% url "timetable_smart_plan" "room" sub.sub.room_old.id %}">
-                {{ sub.sub.room_old.shortcode }}
-            </a>
-        </span>
-    {% endif %}
-{% else %}
-    {% for room in sub.rooms %}
-        <span class="tooltipped" data-position="bottom"
-              data-tooltip="{{ room.name }}">
-            <a href="{% url "timetable_smart_plan" "room" room.id %}">
-                <strong>{{ room.shortcode }}{% if not forloop.last %},{% endif %}</strong>
-            </a>
-        </span>
-    {% endfor %}
-{% endif %}
diff --git a/aleksis/apps/chronos/templates/timetable/subs/subject.html b/aleksis/apps/chronos/templates/timetable/subs/subject.html
deleted file mode 100644
index f8232e9cf1972413bad5339ab8c08d84dad424ca..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/timetable/subs/subject.html
+++ /dev/null
@@ -1,15 +0,0 @@
-{% if not sub.sub.is_event %}
-    {% if sub.sub.type == 3 %}
-        <strong>Aufsicht</strong>
-    {% elif not sub.sub.subject_new and not sub.sub.subject_old %}
-    {% elif sub.sub.type == 1 or sub.sub.type == 2 %}
-        <s>{{ sub.sub.subject_old.shortcode }}</s>
-    {% elif sub.sub.subject_new and sub.sub.subject_old %}
-        <s>{{ sub.sub.subject_old.shortcode }}</s> →
-        <strong>{{ sub.sub.subject_new.shortcode }}</strong>
-    {% elif sub.sub.subject_new and not sub.sub.subject_old %}
-        <strong>{{ sub.sub.subject_new.shortcode }}</strong>
-    {% else %}
-        <strong>{{ sub.sub.subject_old.shortcode }}</strong>
-    {% endif %}
-{% endif %}
diff --git a/aleksis/apps/chronos/templates/timetable/subs/teacher.html b/aleksis/apps/chronos/templates/timetable/subs/teacher.html
deleted file mode 100644
index 4cf5862c798da9072a9fd6d31a882e982b426cdc..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/timetable/subs/teacher.html
+++ /dev/null
@@ -1,44 +0,0 @@
-{% if not sub.is_event %}
-    {% if sub.sub.type == 1 and sub.sub.teacher_old %}
-        <span class="tooltipped" data-position="bottom"
-              data-tooltip="{{ sub.sub.teacher_old.name }}">
-            <a href="{% url "timetable_smart_plan" "teacher" sub.sub.teacher_old.id %}">
-                <s>{{ sub.sub.teacher_old.shortcode }}</s>
-            </a>
-        </span>
-    {% elif sub.sub.teacher_new and sub.sub.teacher_old %}
-        <span class="tooltipped" data-position="bottom"
-              data-tooltip="{{ sub.sub.teacher_old.name }} → {{ sub.sub.teacher_new.name }}">
-            <a href="{% url "timetable_smart_plan" "teacher" sub.sub.teacher_old.id %}">
-                <s>{{ sub.sub.teacher_old.shortcode }}</s>
-            </a>
-            →
-            <a href="{% url "timetable_smart_plan" "teacher" sub.sub.teacher_new.id %}">
-                <strong>{{ sub.sub.teacher_new.shortcode }}</strong>
-            </a>
-        </span>
-    {% elif sub.sub.teacher_new and not sub.sub.teacher_old %}
-        <span class="tooltipped" data-position="bottom"
-              data-tooltip="{{ sub.sub.teacher_new.name }}">
-            <a href="{% url "timetable_smart_plan" "teacher" sub.sub.teacher_new.id %}">
-                <strong>{{ sub.sub.teacher_new.shortcode }}</strong>
-            </a>
-        </span>
-    {% elif sub.sub.teacher_old %}
-        <span class="tooltipped" data-position="bottom"
-              data-tooltip="{{ sub.sub.teacher_old.name }}">
-            <a href="{% url "timetable_smart_plan" "teacher" sub.sub.teacher_old.id %}">
-                <strong>{{ sub.sub.teacher_old.shortcode }}</strong>
-            </a>
-        </span>
-    {% endif %}
-{% else %}
-    {% for teacher in sub.teachers %}
-        <span class="tooltipped" data-position="bottom"
-              data-tooltip="{{ teacher.name }}">
-            <a href="{% url "timetable_smart_plan" "teacher" teacher.id %}">
-                <strong>{{ teacher.shortcode }}{% if not forloop.last %},{% endif %}</strong>
-            </a>
-        </span>
-    {% endfor %}
-{% endif %}
diff --git a/aleksis/apps/chronos/templates/timetable/substitution.html b/aleksis/apps/chronos/templates/timetable/substitution.html
deleted file mode 100644
index ca5983743f6bd98297899fa2bba601e1b14e0a6f..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/templates/timetable/substitution.html
+++ /dev/null
@@ -1,112 +0,0 @@
-{% include 'partials/header.html' %}
-
-
-<script type="text/javascript">
-    var dest = "/timetable/substitutions/";
-</script>
-
-<main>
-    <div class="row no-margin">
-        <div class="col s10 m6">
-            <h4>Vertretungen</h4>
-        </div>
-        <div class="col s2 m6 right align-right print-icon">
-            <a class="waves-effect waves-teal btn-flat btn-flat-medium right"
-               href="
-                    {% if debug %}
-                        {% url "timetable_substitutions_pdf_date" date|date:"Y-m-d" %}
-                    {% else %}
-                       {% url "timetable_substitutions_pdf" %}
-                    {% endif %}
-                    ">
-                <i class="material-icons center">print</i>
-            </a>
-        </div>
-    </div>
-
-    <div class="row no-print">
-        <div class="col s12 m6 l8 xl9">
-            {% if header_info.is_box_needed %}
-                <div class="card">
-                    <div class="card-content">
-                        {% for row in header_info.rows %}
-                            <div class="row no-margin">
-                                <div class="col s3">
-                                    <strong class="truncate">{{ row.0 }}</strong>
-                                </div>
-                                <div class="col s9">
-                                    {{ row.1 }}
-                                </div>
-                            </div>
-                        {% endfor %}
-                    </div>
-                </div>
-            {% endif %}
-
-            {% include "timetable/hintsinsub.html" %}
-        </div>
-        <div class="col s12 m6 l4 xl3">
-            {% include "timetable/datepicker.html" %}
-        </div>
-    </div>
-
-    <h5 class="hide-on-small-and-down">{{ date|date:"l, j. F Y" }}</h5>
-
-    <table class="substitutions striped responsive-table">
-        <thead>
-        <tr>
-            <th><i class="material-icons">people</i></th>
-            <th><i class="material-icons">access_time</i></th>
-            <th>Lehrer</th>
-            <th>Fach</th>
-            <th>Raum</th>
-            <th>Hinweis</th>
-            <th></th>
-        </tr>
-        </thead>
-        <tbody>
-        {% if not sub_table %}
-            <td colspan="7">
-                <p class="flow-text center">
-                    Keine Vertretungen vorhanden
-                </p>
-            </td>
-        {% endif %}
-        {% for sub in sub_table %}
-            <tr class="{{ sub.color }}-text">
-                <td>
-                    {{ sub.classes }}
-                </td>
-                <td>
-                    <strong>
-                        {{ sub.lesson }}
-                    </strong>
-                </td>
-                <td>
-                    {% include "timetable/subs/teacher.html" %}
-                </td>
-                <td>
-                    {% include "timetable/subs/subject.html" %}
-                </td>
-                <td>
-                    {% include "timetable/subs/room.html" %}
-                </td>
-                <td>
-                    {% if sub.badge %}
-                        <span class="badge new green hide-on-med-and-up">{{ sub.badge }}</span>
-                    {% endif %}
-                    <em>{{ sub.text|default:"" }}</em>
-                </td>
-                <td class="hide-on-small-and-down">
-                    {% if sub.badge %}
-                        <span class="badge new green darken-2">{{ sub.badge }}</span>
-                    {% endif %}
-                </td>
-            </tr>
-        {% endfor %}
-        </tbody>
-    </table>
-
-</main>
-
-{% include 'partials/footer.html' %}
diff --git a/aleksis/apps/chronos/templatetags/week_helpers.py b/aleksis/apps/chronos/templatetags/week_helpers.py
index 529d253ae7b9a66879598c794650820358aac29c..26dee1e900e84367e8ec4b1efbcdd8c6d298499e 100644
--- a/aleksis/apps/chronos/templatetags/week_helpers.py
+++ b/aleksis/apps/chronos/templatetags/week_helpers.py
@@ -4,7 +4,7 @@ from typing import Optional, Union
 from django import template
 from django.db.models.query import QuerySet
 
-from ..util import CalendarWeek, week_period_to_date, week_weekday_to_date
+from aleksis.apps.chronos.util.weeks import CalendarWeek, week_period_to_date, week_weekday_to_date
 
 register = template.Library()
 
diff --git a/aleksis/apps/chronos/urls.py b/aleksis/apps/chronos/urls.py
index cf94f08a3115eae77e447046aa21332add8566d3..fb3e7c2e0fe25027493b3d5fcf6c2816846c68a3 100644
--- a/aleksis/apps/chronos/urls.py
+++ b/aleksis/apps/chronos/urls.py
@@ -3,20 +3,24 @@ from django.urls import path
 from . import views
 
 urlpatterns = [
-    path("timetable", views.timetable, name="timetable"),
-    path("timetable/<int:year>/<int:week>", views.timetable, name="timetable_by_week"),
-    path("lessons", views.lessons_day, name="lessons_day"),
-    path("lessons/<when>", views.lessons_day, name="lessons_day_by_date"),
+    path("", views.all_timetables, name="all_timetables"),
+    path("timetable/my/", views.my_timetable, name="my_timetable"),
+    path("timetable/my/<int:year>/<int:month>/<int:day>/", views.my_timetable, name="my_timetable_by_date"),
+    path("timetable/<str:type_>/<int:pk>/", views.timetable, name="timetable"),
+    path("timetable/<str:type_>/<int:pk>/<int:year>/<int:week>/", views.timetable, name="timetable_by_week"),
+    path("timetable/<str:type_>/<int:pk>/<str:regular>/", views.timetable, name="timetable_regular"),
+    path("lessons/", views.lessons_day, name="lessons_day"),
+    path("lessons/<int:year>/<int:month>/<int:day>/", views.lessons_day, name="lessons_day_by_date"),
     path(
-        "lessons/<int:id_>/<int:week>/substition",
+        "lessons/<int:id_>/<int:week>/substition/",
         views.edit_substitution,
         name="edit_substitution",
     ),
     path(
-        "lessons/<int:id_>/<int:week>/substition/delete",
+        "lessons/<int:id_>/<int:week>/substition/delete/",
         views.delete_substitution,
         name="delete_substitution",
     ),
-    path("substitutions", views.substitutions, name="substitutions"),
-    path("substitutions/<int:year>/<int:week>", views.substitutions, name="substitutions_by_week",),
+    path("substitutions/", views.substitutions, name="substitutions"),
+    path("substitutions/<int:year>/<int:month>/<int:day>/", views.substitutions, name="substitutions_by_date"),
 ]
diff --git a/aleksis/apps/chronos/util.py b/aleksis/apps/chronos/util.py
deleted file mode 100644
index c9501c0385d9eba9f3ca3bca611a105c4a53a5cf..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/util.py
+++ /dev/null
@@ -1,106 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from datetime import date, datetime, timedelta
-from typing import Optional, Sequence, Tuple, Union
-
-from django.apps import apps
-from django.db import models
-from django.utils.translation import ugettext as _
-
-
-@dataclass
-class CalendarWeek:
-    """ A calendar week defined by year and ISO week number. """
-
-    year: Optional[int] = None
-    week: Optional[int] = None
-
-    @classmethod
-    def from_date(cls, when: date):
-        """ Get the calendar week by a date object (the week this date is in). """
-
-        week = int(when.strftime("%V"))
-        year = when.year + 1 if when.month == 12 and week == 1 else when.year
-
-        return cls(year=year, week=week)
-
-    @classmethod
-    def current_week(cls) -> int:
-        """ Get the current week number. """
-
-        return cls().week
-
-    @classmethod
-    def weeks_within(cls, start: date, end: date) -> Sequence[CalendarWeek]:
-        """ Get all calendar weeks within a date range. """
-
-        if start > end:
-            raise ValueError("End date must be after start date.")
-
-        current = start
-        weeks = []
-        while current < end:
-            weeks.append(cls.from_date(current))
-            current += timedelta(days=7)
-
-        return weeks
-
-    def __post_init__(self) -> None:
-        today = date.today()
-
-        if not self.year:
-            self.year = today.year
-        if not self.week:
-            self.week = int(today.strftime("%V"))
-
-    def __str__(self) -> str:
-        return "%s %d (%s %s %s)" % (_("Calendar Week"), self.week, self[0], _("to"), self[-1],)
-
-    def __len__(self) -> int:
-        return 7
-
-    def __getitem__(self, n: int) -> date:
-        if n < -7 or n > 6:
-            raise IndexError("Week day %d is out of range." % n)
-
-        if n < 0:
-            n += 7
-
-        return datetime.strptime("%d-%d-%d" % (self.year, self.week, n + 1), "%G-%V-%u").date()
-
-    def __contains__(self, day: date) -> bool:
-        return self.__class__.form_date(day) == self
-
-    def __eq__(self, other: CalendarWeek) -> bool:
-        return self.year == other.year and self.week == other.week
-
-    def __lt__(self, other: CalendarWeek) -> bool:
-        return self[0] < other[0]
-
-    def __gt__(self, other: CalendarWeek) -> bool:
-        return self[0] > other[0]
-
-    def __le__(self, other: CalendarWeek) -> bool:
-        return self[0] <= other[0]
-
-    def __gr__(self, other: CalendarWeek) -> bool:
-        return self[0] >= other[0]
-
-    def __add__(self, weeks: int) -> CalendarWeek:
-        return self.__class__.from_date(self[0] + timedelta(days=weeks * 7))
-
-    def __sub__(self, weeks: int) -> CalendarWeek:
-        return self.__class__.from_date(self[0] - timedelta(days=weeks * 7))
-
-
-def week_weekday_from_date(when: date) -> Tuple[CalendarWeek, int]:
-    return (CalendarWeek.from_date(when), when.isoweekday())
-
-
-def week_weekday_to_date(week: CalendarWeek, weekday: int) -> date:
-    return week[weekday - 1]
-
-
-def week_period_to_date(week: Union[CalendarWeek, int], period) -> date:
-    return period.get_date(week)
diff --git a/aleksis/apps/chronos/util/js.py b/aleksis/apps/chronos/util/js.py
new file mode 100644
index 0000000000000000000000000000000000000000..eb9082b0e46bcb06090ae853561d5c86c159ce56
--- /dev/null
+++ b/aleksis/apps/chronos/util/js.py
@@ -0,0 +1,8 @@
+from datetime import datetime, time, date
+
+
+def date_unix(value: date) -> int:
+    """ Converts a date object to an UNIX timestamp """
+
+    value = datetime.combine(value, time(hour=0, minute=0))
+    return int(value.timestamp()) * 1000
diff --git a/aleksis/apps/chronos/util/min_max.py b/aleksis/apps/chronos/util/min_max.py
new file mode 100644
index 0000000000000000000000000000000000000000..4d5dd421443f36b3b2f01ce0a2ef74b6504a0b5e
--- /dev/null
+++ b/aleksis/apps/chronos/util/min_max.py
@@ -0,0 +1,19 @@
+from django.db.models import Min, Max
+
+from aleksis.apps.chronos.models import TimePeriod
+
+# Determine overall first and last day and period
+min_max = TimePeriod.objects.aggregate(
+    Min("period"), Max("period"), Min("weekday"), Max("weekday"), Min("time_start"), Max("time_end")
+)
+
+period_min = min_max.get("period__min", 1)
+period_max = min_max.get("period__max", 7)
+
+time_min = min_max.get("time_start__min", None)
+time_max = min_max.get("time_end__max", None)
+
+weekday_min_ = min_max.get("weekday__min", 0)
+weekday_max = min_max.get("weekday__max", 6)
+
+
diff --git a/aleksis/apps/chronos/util/prev_next.py b/aleksis/apps/chronos/util/prev_next.py
new file mode 100644
index 0000000000000000000000000000000000000000..c0a844dc40e728a17c98e6289def5bd69c1dd9b9
--- /dev/null
+++ b/aleksis/apps/chronos/util/prev_next.py
@@ -0,0 +1,48 @@
+from datetime import timedelta, date, time
+from typing import Optional, Tuple
+
+from calendarweek import CalendarWeek
+from django.urls import reverse
+from django.utils import timezone
+
+from aleksis.apps.chronos.util.min_max import weekday_min_, weekday_max, time_max
+
+
+def get_next_relevant_day(day: Optional[date] = None, time: Optional[time] = None, prev: bool = False) -> date:
+    """ Returns next (previous) day with lessons depending on date and time """
+
+    if day is None:
+        day = timezone.now().date()
+
+    if time is not None and not prev:
+        if time > time_max:
+            day += timedelta(days=1)
+
+    cw = CalendarWeek.from_date(day)
+
+    if day.weekday() > weekday_max:
+        if prev:
+            day = cw[weekday_max]
+        else:
+            cw += 1
+            day = cw[weekday_min_]
+    elif day.weekday() < weekday_min_:
+        if prev:
+            cw -= 1
+            day = cw[weekday_max]
+        else:
+            day = cw[weekday_min_]
+
+    return day
+
+
+def get_prev_next_by_day(day: date, url: str) -> Tuple[str, str]:
+    """ Build URLs for previous/next day """
+
+    day_prev = get_next_relevant_day(day - timedelta(days=1), prev=True)
+    day_next = get_next_relevant_day(day + timedelta(days=1))
+
+    url_prev = reverse(url, args=[day_prev.year, day_prev.month, day_prev.day])
+    url_next = reverse(url, args=[day_next.year, day_next.month, day_next.day])
+
+    return url_prev, url_next
diff --git a/aleksis/apps/chronos/util/weeks.py b/aleksis/apps/chronos/util/weeks.py
new file mode 100644
index 0000000000000000000000000000000000000000..32ec8b81f006d0332b5be8b1502043a1c1806766
--- /dev/null
+++ b/aleksis/apps/chronos/util/weeks.py
@@ -0,0 +1,30 @@
+from datetime import date
+from typing import Tuple, List, Union
+
+from calendarweek import CalendarWeek
+
+
+def week_weekday_from_date(when: date) -> Tuple[CalendarWeek, int]:
+    return (CalendarWeek.from_date(when), when.weekday())
+
+
+def week_weekday_to_date(week: CalendarWeek, weekday: int) -> date:
+    return week[weekday - 1]
+
+
+def week_period_to_date(week: Union[CalendarWeek, int], period) -> date:
+    return period.get_date(week)
+
+
+def get_weeks_for_year(year: int) -> List[CalendarWeek]:
+    """ Generates all weeks for one year """
+    weeks = []
+
+    # Go for all weeks in year and create week list
+    current_week = CalendarWeek(year=year, week=1)
+
+    while current_week.year == year:
+        weeks.append(current_week)
+        current_week += 1
+
+    return weeks
diff --git a/aleksis/apps/chronos/views.py b/aleksis/apps/chronos/views.py
index 966dc0b831ffe457c661c09228d2f9d1bb7ed1cb..90cac9127e56297b181583de6d8b0572024b59b6 100644
--- a/aleksis/apps/chronos/views.py
+++ b/aleksis/apps/chronos/views.py
@@ -1,130 +1,242 @@
 from collections import OrderedDict
 from datetime import date, datetime, timedelta
-from typing import Optional
+from typing import Optional, Tuple
 
 from django.contrib.auth.decorators import login_required
-from django.db.models import Max, Min
-from django.http import HttpRequest, HttpResponse
+from django.db.models import Count
+from django.http import HttpRequest, HttpResponse, HttpResponseNotFound
 from django.shortcuts import get_object_or_404, redirect, render
 from django.urls import reverse
+from django.utils import timezone
 from django.utils.translation import ugettext as _
-
 from django_tables2 import RequestConfig
 
 from aleksis.core.decorators import admin_required
+from aleksis.core.models import Person, Group
 from aleksis.core.util import messages
+from .forms import LessonSubstitutionForm
+from .models import LessonPeriod, LessonSubstitution, TimePeriod, Room
+from .tables import LessonsTable
+from .util.js import date_unix
+from .util.min_max import (
+    period_min,
+    period_max,
+    weekday_min_,
+    weekday_max
+)
+from .util.prev_next import get_next_relevant_day, get_prev_next_by_day
+from .util.weeks import CalendarWeek, get_weeks_for_year
+from aleksis.core.util.core_helpers import has_person
+
+
+@login_required
+def all_timetables(request: HttpRequest) -> HttpResponse:
+    context = {}
+
+    teachers = Person.objects.annotate(
+        lessons_count=Count("lessons_as_teacher")
+    ).filter(lessons_count__gt=0)
+    classes = Group.objects.annotate(lessons_count=Count("lessons")).filter(
+        lessons_count__gt=0, parent_groups=None
+    )
+    rooms = Room.objects.annotate(lessons_count=Count("lesson_periods")).filter(
+        lessons_count__gt=0
+    )
+
+    context["teachers"] = teachers
+    context["classes"] = classes
+    context["rooms"] = rooms
+
+    return render(request, "chronos/all.html", context)
+
+
+@login_required
+def my_timetable(
+    request: HttpRequest,
+    year: Optional[int] = None,
+    month: Optional[int] = None,
+    day: Optional[int] = None,
+) -> HttpResponse:
+    context = {}
+
+    if day:
+        wanted_day = timezone.datetime(year=year, month=month, day=day).date()
+        wanted_day = get_next_relevant_day(wanted_day)
+    else:
+        wanted_day = get_next_relevant_day(timezone.now().date(), datetime.now().time())
+
+    if has_person(request.user):
+        person = request.user.person
+
+        if person.is_teacher:
+            # Teacher
+
+            type_ = "teacher"
+            super_el = person
+            lesson_periods_person = person.lesson_periods_as_teacher
+
+        elif person.primary_group:
+            # Student
+
+            type_ = "group"
+            super_el = person.primary_group
+            lesson_periods_person = person.lesson_periods_as_participant
+
+        else:
+            # If no student or teacher, redirect to all timetables
+            return redirect("all_timetables")
+
+    lesson_periods = lesson_periods_person.on_day(wanted_day)
+
+    # Build dictionary with lessons
+    per_period = {}
+    for lesson_period in lesson_periods:
+        if lesson_period.period.period in per_period:
+            per_period[lesson_period.period.period].append(lesson_period)
+        else:
+            per_period[lesson_period.period.period] = [lesson_period]
+
+    context["lesson_periods"] = OrderedDict(sorted(per_period.items()))
+    context["super"] = {"type": type_, "el": super_el}
+    context["type"] = type_
+    context["day"] = wanted_day
+    context["periods"] = TimePeriod.get_times_dict()
+    context["smart"] = True
 
-from .forms import LessonSubstitutionForm, SelectForm
-from .models import LessonPeriod, LessonSubstitution, TimePeriod
-from .tables import LessonsTable, SubstitutionsTable
-from .util import CalendarWeek
+    context["url_prev"], context["url_next"] = get_prev_next_by_day(
+        wanted_day, "my_timetable_by_date"
+    )
+
+    return render(request, "chronos/my_timetable.html", context)
 
 
 @login_required
 def timetable(
-    request: HttpRequest, year: Optional[int] = None, week: Optional[int] = None
+    request: HttpRequest,
+    type_: str,
+    pk: int,
+    year: Optional[int] = None,
+    week: Optional[int] = None,
+    regular: Optional[str] = None,
 ) -> HttpResponse:
     context = {}
 
+    is_smart = regular != "regular"
+
+    if type_ == "group":
+        el = get_object_or_404(Group, pk=pk)
+    elif type_ == "teacher":
+        el = get_object_or_404(Person, pk=pk)
+    elif type_ == "room":
+        el = get_object_or_404(Room, pk=pk)
+    else:
+        return HttpResponseNotFound()
+
     if year and week:
         wanted_week = CalendarWeek(year=year, week=week)
     else:
+        # TODO: On not used days show next week
         wanted_week = CalendarWeek()
 
     lesson_periods = LessonPeriod.objects.in_week(wanted_week)
-
-    # Incrementally filter lesson periods by GET parameters
-    if (
-        request.GET.get("group", None)
-        or request.GET.get("teacher", None)
-        or request.GET.get("room", None)
-    ):
-        lesson_periods = lesson_periods.filter_from_query(request.GET)
-    else:
-        # Redirect to a selected view if no filter provided
-        if request.user.person:
-            if request.user.person.primary_group:
-                return redirect(
-                    reverse("timetable") + "?group=%d" % request.user.person.primary_group.pk
-                )
-            elif lesson_periods.filter(lesson__teachers=request.user.person).exists():
-                return redirect(reverse("timetable") + "?teacher=%d" % request.user.person.pk)
+    lesson_periods = lesson_periods.filter_from_type(type_, pk)
 
     # Regroup lesson periods per weekday
-    per_day = {}
+    per_period = {}
     for lesson_period in lesson_periods:
-        per_day.setdefault(lesson_period.period.weekday, {})[
-            lesson_period.period.period
-        ] = lesson_period
-
-    # Determine overall first and last day and period
-    min_max = TimePeriod.objects.aggregate(
-        Min("period"), Max("period"), Min("weekday"), Max("weekday")
-    )
+        added = False
+        if lesson_period.period.period in per_period:
+            if lesson_period.period.weekday in per_period[lesson_period.period.period]:
+                per_period[lesson_period.period.period][
+                    lesson_period.period.weekday
+                ].append(lesson_period)
+                added = True
+
+        if not added:
+            per_period.setdefault(lesson_period.period.period, {})[
+                lesson_period.period.weekday
+            ] = [lesson_period]
 
     # Fill in empty lessons
-    for weekday_num in range(min_max.get("weekday__min", 0), min_max.get("weekday__max", 6) + 1):
+    for period_num in range(period_min, period_max + 1):
         # Fill in empty weekdays
-        if weekday_num not in per_day.keys():
-            per_day[weekday_num] = {}
+        if period_num not in per_period.keys():
+            per_period[period_num] = {}
 
         # Fill in empty lessons on this workday
-        for period_num in range(min_max.get("period__min", 1), min_max.get("period__max", 7) + 1):
-            if period_num not in per_day[weekday_num].keys():
-                per_day[weekday_num][period_num] = None
+        for weekday_num in range(weekday_min_, weekday_max + 1):
+            if weekday_num not in per_period[period_num].keys():
+                per_period[period_num][weekday_num] = []
 
         # Order this weekday by periods
-        per_day[weekday_num] = OrderedDict(sorted(per_day[weekday_num].items()))
+        per_period[period_num] = OrderedDict(sorted(per_period[period_num].items()))
 
-    # Add a form to filter the view
-    select_form = SelectForm(request.GET or None)
-
-    context["current_head"] = _("Timetable")
-    context["lesson_periods"] = OrderedDict(sorted(per_day.items()))
+    context["lesson_periods"] = OrderedDict(sorted(per_period.items()))
     context["periods"] = TimePeriod.get_times_dict()
-    context["weekdays"] = dict(TimePeriod.WEEKDAY_CHOICES)
+    context["weekdays"] = dict(
+        TimePeriod.WEEKDAY_CHOICES[weekday_min_ : weekday_max + 1]
+    )
+    context["weekdays_short"] = dict(
+        TimePeriod.WEEKDAY_CHOICES_SHORT[weekday_min_ : weekday_max + 1]
+    )
+    context["weeks"] = get_weeks_for_year(year=wanted_week.year)
     context["week"] = wanted_week
-    context["select_form"] = select_form
+    context["type"] = type_
+    context["pk"] = pk
+    context["el"] = el
+    context["smart"] = is_smart
+    context["week_select"] = {
+        "year": wanted_week.year,
+        "dest": reverse("timetable", args=[type_, pk])
+    }
 
     week_prev = wanted_week - 1
     week_next = wanted_week + 1
-    context["url_prev"] = "%s?%s" % (
-        reverse("timetable_by_week", args=[week_prev.year, week_prev.week]),
-        request.GET.urlencode(),
+
+    context["url_prev"] = reverse(
+        "timetable_by_week", args=[type_, pk, week_prev.year, week_prev.week]
     )
-    context["url_next"] = "%s?%s" % (
-        reverse("timetable_by_week", args=[week_next.year, week_next.week]),
-        request.GET.urlencode(),
+    context["url_next"] = reverse(
+        "timetable_by_week", args=[type_, pk, week_next.year, week_next.week]
     )
 
-    return render(request, "chronos/tt_week.html", context)
+    return render(request, "chronos/timetable.html", context)
 
 
 @login_required
-def lessons_day(request: HttpRequest, when: Optional[str] = None) -> HttpResponse:
+def lessons_day(
+    request: HttpRequest,
+    year: Optional[int] = None,
+    month: Optional[int] = None,
+    day: Optional[int] = None,
+) -> HttpResponse:
     context = {}
 
-    if when:
-        day = datetime.strptime(when, "%Y-%m-%d").date()
+    if day:
+        wanted_day = timezone.datetime(year=year, month=month, day=day).date()
+        wanted_day = get_next_relevant_day(wanted_day)
     else:
-        day = date.today()
+        wanted_day = get_next_relevant_day(timezone.now().date(), datetime.now().time())
 
     # Get lessons
-    lesson_periods = LessonPeriod.objects.on_day(day)
+    lesson_periods = LessonPeriod.objects.on_day(wanted_day)
 
     # Build table
     lessons_table = LessonsTable(lesson_periods.all())
     RequestConfig(request).configure(lessons_table)
 
-    context["current_head"] = _("Lessons %s") % (day)
     context["lessons_table"] = lessons_table
-    context["day"] = day
+    context["day"] = wanted_day
     context["lesson_periods"] = lesson_periods
 
-    day_prev = day - timedelta(days=1)
-    day_next = day + timedelta(days=1)
-    context["url_prev"] = reverse("lessons_day_by_date", args=[day_prev.strftime("%Y-%m-%d")])
-    context["url_next"] = reverse("lessons_day_by_date", args=[day_next.strftime("%Y-%m-%d")])
+    context["datepicker"] = {
+        "date": date_unix(wanted_day),
+        "dest": reverse("lessons_day")
+    }
+
+    context["url_prev"], context["url_next"] = get_prev_next_by_day(
+        wanted_day, "lessons_day_by_date"
+    )
 
     return render(request, "chronos/lessons_day.html", context)
 
@@ -156,9 +268,11 @@ def edit_substitution(request: HttpRequest, id_: int, week: int) -> HttpResponse
             edit_substitution_form.save(commit=True)
 
             messages.success(request, _("The substitution has been saved."))
+
+            date = wanted_week[lesson_period.period.weekday]
             return redirect(
                 "lessons_day_by_date",
-                when=wanted_week[lesson_period.period.weekday - 1].strftime("%Y-%m-%d"),
+                year=date.year, month=date.month, day=date.day
             )
 
     context["edit_substitution_form"] = edit_substitution_form
@@ -168,45 +282,48 @@ def edit_substitution(request: HttpRequest, id_: int, week: int) -> HttpResponse
 
 @admin_required
 def delete_substitution(request: HttpRequest, id_: int, week: int) -> HttpResponse:
-    context = {}
-
     lesson_period = get_object_or_404(LessonPeriod, pk=id_)
     wanted_week = lesson_period.lesson.get_calendar_week(week)
 
-    LessonSubstitution.objects.filter(week=wanted_week.week, lesson_period=lesson_period).delete()
+    LessonSubstitution.objects.filter(
+        week=wanted_week.week, lesson_period=lesson_period
+    ).delete()
 
     messages.success(request, _("The substitution has been deleted."))
+
+    date = wanted_week[lesson_period.period.weekday]
     return redirect(
         "lessons_day_by_date",
-        when=wanted_week[lesson_period.period.weekday - 1].strftime("%Y-%m-%d"),
+        year=date.year, month=date.month, day=date.day
     )
 
 
+@login_required
 def substitutions(
-    request: HttpRequest, year: Optional[int] = None, week: Optional[int] = None
+    request: HttpRequest,
+    year: Optional[int] = None,
+    month: Optional[int] = None,
+    day: Optional[int] = None,
 ) -> HttpResponse:
     context = {}
 
-    if week:
-        wanted_week = CalendarWeek(year=year, week=week)
+    if day:
+        wanted_day = timezone.datetime(year=year, month=month, day=day).date()
+        wanted_day = get_next_relevant_day(wanted_day)
     else:
-        wanted_week = CalendarWeek()
+        wanted_day = get_next_relevant_day(timezone.now().date(), datetime.now().time())
 
-    substitutions = LessonSubstitution.objects.filter(week=wanted_week.week)
+    substitutions = LessonSubstitution.objects.on_day(wanted_day)
 
-    # Prepare table
-    substitutions_table = SubstitutionsTable(substitutions)
-    RequestConfig(request).configure(substitutions_table)
+    context["substitutions"] = substitutions
+    context["day"] = wanted_day
+    context["datepicker"] = {
+        "date": date_unix(wanted_day),
+        "dest": reverse("substitutions")
+    }
 
-    context["current_head"] = str(wanted_week)
-    context["substitutions_table"] = substitutions_table
-    week_prev = wanted_week - 1
-    week_next = wanted_week + 1
-    context["url_prev"] = "%s" % (
-        reverse("substitutions_by_week", args=[week_prev.year, week_prev.week])
-    )
-    context["url_next"] = "%s" % (
-        reverse("substitutions_by_week", args=[week_next.year, week_next.week])
+    context["url_prev"], context["url_next"] = get_prev_next_by_day(
+        wanted_day, "substitutions_by_date"
     )
 
     return render(request, "chronos/substitutions.html", context)
diff --git a/poetry.lock b/poetry.lock
index 1be77e4f6088b9a87a981292867ac28a64928828..28e6962c2c88ad1487dfccbf777f814cff0d214a 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,6 +1,7 @@
 [[package]]
 category = "main"
 description = ""
+develop = true
 name = "aleksis"
 optional = false
 python-versions = "^3.7"
@@ -9,9 +10,11 @@ version = "1.0a4.dev0"
 [package.dependencies]
 Django = "^3.0"
 Pillow = "^7.0"
+calendarweek = "^0.4.3"
 colour = "^0.1.5"
 django-any-js = "^1.0"
 django-bootstrap4 = "^1.0"
+django-ckeditor = "^5.8.0"
 django-debug-toolbar = "^2.0"
 django-easy-audit = "^1.2rc1"
 django-filter = "^2.2.0"
@@ -19,6 +22,7 @@ django-hattori = "^0.2"
 django-image-cropping = "^1.2"
 django-impersonate = "^1.4"
 django-ipware = "^2.1"
+django-js-reverse = "^0.9.1"
 django-maintenance-mode = "^0.14.0"
 django-material = "^1.6.0"
 django-menu-generator = "^1.0.4"
@@ -27,10 +31,12 @@ django-pwa = "^1.0.6"
 django-sass-processor = "^0.8"
 django-settings-context-processor = "^0.2"
 django-tables2 = "^2.1"
+django-templated-email = "^2.3.0"
 django-yarnpkg = "^6.0"
 django_select2 = "^7.1"
 django_widget_tweaks = "^1.4.5"
 easy-thumbnails = "^2.6"
+html2text = "^2020.0.0"
 libsass = "^0.19.2"
 psycopg2 = "^2.8"
 python-memcached = "^1.59"
@@ -53,6 +59,7 @@ extras = ["yaml", "toml", "ini"]
 version = "^2.0"
 
 [package.extras]
+celery = ["Celery (^4.4.0)", "django-celery-results (^1.1.2)", "django-celery-beat (^1.5.0)", "django-celery-email (^3.0.0)"]
 ldap = ["django-auth-ldap (^2.0)"]
 
 [package.source]
@@ -97,6 +104,17 @@ soupsieve = ">=1.2"
 html5lib = ["html5lib"]
 lxml = ["lxml"]
 
+[[package]]
+category = "main"
+description = "Utilities for working with calendar weeks in Python and Django"
+name = "calendarweek"
+optional = false
+python-versions = ">=3.7,<4.0"
+version = "0.4.4"
+
+[package.extras]
+django = ["Django (>=2.2,<4.0)"]
+
 [[package]]
 category = "main"
 description = "Python package for providing Mozilla's CA Bundle."
@@ -149,9 +167,6 @@ optional = false
 python-versions = "*"
 version = "5.0.6"
 
-[package.dependencies]
-six = "*"
-
 [[package]]
 category = "main"
 description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
@@ -214,6 +229,17 @@ version = "2.2.0"
 [package.dependencies]
 Django = ">=1.8"
 
+[[package]]
+category = "main"
+description = "Django admin CKEditor integration."
+name = "django-ckeditor"
+optional = false
+python-versions = "*"
+version = "5.8.0"
+
+[package.dependencies]
+django-js-asset = ">=1.2.2"
+
 [[package]]
 category = "main"
 description = "Django live settings with pluggable backends, including Redis."
@@ -322,6 +348,25 @@ optional = false
 python-versions = "*"
 version = "2.1.0"
 
+[[package]]
+category = "main"
+description = "script tag with additional attributes for django.forms.Media"
+name = "django-js-asset"
+optional = false
+python-versions = "*"
+version = "1.2.2"
+
+[[package]]
+category = "main"
+description = "Javascript url handling for Django that doesn't hurt."
+name = "django-js-reverse"
+optional = false
+python-versions = "*"
+version = "0.9.1"
+
+[package.dependencies]
+Django = ">=1.5"
+
 [[package]]
 category = "main"
 description = "django-maintenance-mode shows a 503 error page when maintenance-mode is on."
@@ -433,6 +478,17 @@ version = "1.0.6"
 [package.dependencies]
 django = ">=1.8"
 
+[[package]]
+category = "main"
+description = "Render a particular block from a template to a string."
+name = "django-render-block"
+optional = false
+python-versions = "*"
+version = "0.6"
+
+[package.dependencies]
+django = ">=1.11"
+
 [[package]]
 category = "main"
 description = "SASS processor to compile SCSS files into *.css, while rendering, or offline."
@@ -479,6 +535,18 @@ Django = ">=1.11"
 [package.extras]
 tablib = ["tablib"]
 
+[[package]]
+category = "main"
+description = "A Django oriented templated / transaction email abstraction"
+name = "django-templated-email"
+optional = false
+python-versions = "*"
+version = "2.3.0"
+
+[package.dependencies]
+django-render-block = ">=0.5"
+six = ">=1"
+
 [[package]]
 category = "main"
 description = "Complete Two-Factor Authentication for Django"
@@ -587,14 +655,21 @@ category = "main"
 description = "Faker is a Python package that generates fake data for you."
 name = "faker"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-version = "3.0.0"
+python-versions = ">=3.4"
+version = "4.0.0"
 
 [package.dependencies]
 python-dateutil = ">=2.4"
-six = ">=1.10"
 text-unidecode = "1.3"
 
+[[package]]
+category = "main"
+description = "Turn HTML into equivalent Markdown-structured text."
+name = "html2text"
+optional = false
+python-versions = ">=3.5"
+version = "2020.1.16"
+
 [[package]]
 category = "main"
 description = "Internationalized Domain Names in Applications (IDNA)"
@@ -620,7 +695,7 @@ description = "Python version of Google's common library for parsing, formatting
 name = "phonenumbers"
 optional = false
 python-versions = "*"
-version = "8.11.1"
+version = "8.11.2"
 
 [[package]]
 category = "main"
@@ -716,7 +791,7 @@ category = "main"
 description = "YAML parser and emitter for Python"
 name = "pyyaml"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+python-versions = "*"
 version = "5.3"
 
 [[package]]
@@ -760,8 +835,8 @@ category = "main"
 description = "Python 2 and 3 compatibility utilities"
 name = "six"
 optional = false
-python-versions = ">=2.6, !=3.0.*, !=3.1.*"
-version = "1.13.0"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+version = "1.14.0"
 
 [[package]]
 category = "main"
@@ -812,7 +887,7 @@ description = "Twilio API client and TwiML generator"
 name = "twilio"
 optional = false
 python-versions = "*"
-version = "6.35.1"
+version = "6.35.2"
 
 [package.dependencies]
 PyJWT = ">=1.4.2"
@@ -849,7 +924,7 @@ pycryptodome = "*"
 six = "*"
 
 [metadata]
-content-hash = "61923d9b1cbc5b40a1fc873e212a307b49d4ec4a47d37c9d56d9e76017afe3ce"
+content-hash = "f2db0ef57bb256e1e7f9ae769792ce2b3288a37dccbae621f568844e2a656d0c"
 python-versions = "^3.7"
 
 [metadata.files]
@@ -867,6 +942,10 @@ beautifulsoup4 = [
     {file = "beautifulsoup4-4.8.2-py3-none-any.whl", hash = "sha256:9fbb4d6e48ecd30bcacc5b63b94088192dcda178513b2ae3c394229f8911b887"},
     {file = "beautifulsoup4-4.8.2.tar.gz", hash = "sha256:05fd825eb01c290877657a56df4c6e4c311b3965bda790c613a3d6fb01a5462a"},
 ]
+calendarweek = [
+    {file = "calendarweek-0.4.4-py3-none-any.whl", hash = "sha256:6510a42015558f140ed6677e79efbb45d8bf87ccded069db4026283eb639a256"},
+    {file = "calendarweek-0.4.4.tar.gz", hash = "sha256:02f092ec54ebe162dc9f3614de6efbf3d7fb35115e8ca5d62e99d65c342f5732"},
+]
 certifi = [
     {file = "certifi-2019.11.28-py2.py3-none-any.whl", hash = "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3"},
     {file = "certifi-2019.11.28.tar.gz", hash = "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"},
@@ -909,6 +988,10 @@ django-bulk-update = [
     {file = "django-bulk-update-2.2.0.tar.gz", hash = "sha256:5ab7ce8a65eac26d19143cc189c0f041d5c03b9d1b290ca240dc4f3d6aaeb337"},
     {file = "django_bulk_update-2.2.0-py2.py3-none-any.whl", hash = "sha256:49a403392ae05ea872494d74fb3dfa3515f8df5c07cc277c3dc94724c0ee6985"},
 ]
+django-ckeditor = [
+    {file = "django-ckeditor-5.8.0.tar.gz", hash = "sha256:46fc9c7346ea36183dc0cea350f98704f8b04c4722b7fe4fb18baf8ae20423fb"},
+    {file = "django_ckeditor-5.8.0-py2.py3-none-any.whl", hash = "sha256:a59bab13f4481318f8a048b1b0aef5c7da768a6352dcfb9ba0e77d91fbb9462a"},
+]
 django-constance = []
 django-debug-toolbar = [
     {file = "django-debug-toolbar-2.1.tar.gz", hash = "sha256:24c157bc6c0e1648e0a6587511ecb1b007a00a354ce716950bff2de12693e7a8"},
@@ -939,6 +1022,14 @@ django-impersonate = [
 django-ipware = [
     {file = "django-ipware-2.1.0.tar.gz", hash = "sha256:a7c7a8fd019dbdc9c357e6e582f65034e897572fc79a7e467674efa8aef9d00b"},
 ]
+django-js-asset = [
+    {file = "django-js-asset-1.2.2.tar.gz", hash = "sha256:c163ae80d2e0b22d8fb598047cd0dcef31f81830e127cfecae278ad574167260"},
+    {file = "django_js_asset-1.2.2-py2.py3-none-any.whl", hash = "sha256:8ec12017f26eec524cab436c64ae73033368a372970af4cf42d9354fcb166bdd"},
+]
+django-js-reverse = [
+    {file = "django-js-reverse-0.9.1.tar.gz", hash = "sha256:2a392d169f44e30b883c30dfcfd917a14167ce8fe196c99d2385b31c90d77aa0"},
+    {file = "django_js_reverse-0.9.1-py2.py3-none-any.whl", hash = "sha256:8134c2ab6307c945edfa90671ca65e85d6c1754d48566bdd6464be259cc80c30"},
+]
 django-maintenance-mode = [
     {file = "django-maintenance-mode-0.14.0.tar.gz", hash = "sha256:f3fef1760fdcda5e0bf6c2966aadc77eea6f328580a9c751920daba927281a68"},
     {file = "django_maintenance_mode-0.14.0-py2-none-any.whl", hash = "sha256:b4cc24a469ed10897826a28f05d64e6166a58d130e4940ac124ce198cd4cc778"},
@@ -973,6 +1064,9 @@ django-pwa = [
     {file = "django-pwa-1.0.6.tar.gz", hash = "sha256:b3f1ad0c5241fae4c7505423540de4db93077d7c88416ff6d2af545ffe209f34"},
     {file = "django_pwa-1.0.6-py3-none-any.whl", hash = "sha256:9306105fcb637ae16fea6527be4b147d45fd53db85efb1d4f61dfea6bf793e56"},
 ]
+django-render-block = [
+    {file = "django_render_block-0.6-py2.py3-none-any.whl", hash = "sha256:95c7dc9610378a10e0c4a10d8364ec7307210889afccd6a67a6aaa0fd599bd4d"},
+]
 django-sass-processor = [
     {file = "django-sass-processor-0.8.tar.gz", hash = "sha256:e039551994feaaba6fcf880412b25a772dd313162a34cbb4289814988cfae340"},
 ]
@@ -987,6 +1081,9 @@ django-tables2 = [
     {file = "django-tables2-2.2.1.tar.gz", hash = "sha256:0d9b17f5c030ba1b5fcaeb206d8397bf58f1fdfc6beaf56e7874841b8647aa94"},
     {file = "django_tables2-2.2.1-py2.py3-none-any.whl", hash = "sha256:6afa0496695e15b332e98537265d09fe01a55b28c75a85323d8e6b0dc2350280"},
 ]
+django-templated-email = [
+    {file = "django-templated-email-2.3.0.tar.gz", hash = "sha256:536c4e5ae099eabfb9aab36087d4d7799948c654e73da55a744213d086d5bb33"},
+]
 django-two-factor-auth = [
     {file = "django-two-factor-auth-1.10.0.tar.gz", hash = "sha256:3c3af3cd747462be18e7494c4068a2bdc606d7a2d2b2914f8d4590fc80995a71"},
     {file = "django_two_factor_auth-1.10.0-py2.py3-none-any.whl", hash = "sha256:0945260fa84e4522d8fa951c35e401616579fd8564938441614399dc588a1c1f"},
@@ -1006,8 +1103,12 @@ easy-thumbnails = [
     {file = "easy-thumbnails-2.7.tar.gz", hash = "sha256:e4e7a0dd4001f56bfd4058428f2c91eafe27d33ef3b8b33ac4e013b159b9ff91"},
 ]
 faker = [
-    {file = "Faker-3.0.0-py2.py3-none-any.whl", hash = "sha256:202ad3b2ec16ae7c51c02904fb838831f8d2899e61bf18db1e91a5a582feab11"},
-    {file = "Faker-3.0.0.tar.gz", hash = "sha256:92c84a10bec81217d9cb554ee12b3838c8986ce0b5d45f72f769da22e4bb5432"},
+    {file = "Faker-4.0.0-py3-none-any.whl", hash = "sha256:047d4d1791bfb3756264da670d99df13d799bb36e7d88774b1585a82d05dbaec"},
+    {file = "Faker-4.0.0.tar.gz", hash = "sha256:1b1a58961683b30c574520d0c739c4443e0ef6a185c04382e8cc888273dbebed"},
+]
+html2text = [
+    {file = "html2text-2020.1.16-py3-none-any.whl", hash = "sha256:c7c629882da0cf377d66f073329ccf34a12ed2adf0169b9285ae4e63ef54c82b"},
+    {file = "html2text-2020.1.16.tar.gz", hash = "sha256:e296318e16b059ddb97f7a8a1d6a5c1d7af4544049a01e261731d2d5cc277bbb"},
 ]
 idna = [
     {file = "idna-2.8-py2.py3-none-any.whl", hash = "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"},
@@ -1032,8 +1133,8 @@ libsass = [
     {file = "libsass-0.19.4.tar.gz", hash = "sha256:8b5b6d1a7c4ea1d954e0982b04474cc076286493f6af2d0a13c2e950fbe0be95"},
 ]
 phonenumbers = [
-    {file = "phonenumbers-8.11.1-py2.py3-none-any.whl", hash = "sha256:aaa19bc1f2c7efbf7a94be33558e0c5b71620377c9271692d3e314c558962460"},
-    {file = "phonenumbers-8.11.1.tar.gz", hash = "sha256:239507184ee5b1b83557005af1d5fcce70f83ae18f5dff45b94a67226db10d63"},
+    {file = "phonenumbers-8.11.2-py2.py3-none-any.whl", hash = "sha256:796ba25c3064727ca0b8edf7a8ef5ef247c6da37aee498562e6e0ed46970a57f"},
+    {file = "phonenumbers-8.11.2.tar.gz", hash = "sha256:a22d3b14c7f18af9be7c4ade92285035f621c6a17b75352dc9c2e5d146aee348"},
 ]
 pillow = [
     {file = "Pillow-7.0.0-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:5f3546ceb08089cedb9e8ff7e3f6a7042bb5b37c2a95d392fb027c3e53a2da00"},
@@ -1154,8 +1255,8 @@ requests = [
     {file = "requests-2.22.0.tar.gz", hash = "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4"},
 ]
 six = [
-    {file = "six-1.13.0-py2.py3-none-any.whl", hash = "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd"},
-    {file = "six-1.13.0.tar.gz", hash = "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"},
+    {file = "six-1.14.0-py2.py3-none-any.whl", hash = "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"},
+    {file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"},
 ]
 soupsieve = [
     {file = "soupsieve-1.9.5-py2.py3-none-any.whl", hash = "sha256:bdb0d917b03a1369ce964056fc195cfdff8819c40de04695a80bc813c3cfa1f5"},
@@ -1179,7 +1280,7 @@ tqdm = [
     {file = "tqdm-4.41.1.tar.gz", hash = "sha256:4789ccbb6fc122b5a6a85d512e4e41fc5acad77216533a6f2b8ce51e0f265c23"},
 ]
 twilio = [
-    {file = "twilio-6.35.1.tar.gz", hash = "sha256:c784e55d150ebeb2ba837afbab7168edfb91db57e77a9da49f2a1892688a1930"},
+    {file = "twilio-6.35.2.tar.gz", hash = "sha256:a086443642c0e1f13c8f8f087b426ca81ec883efbe496d8279180a49bb9287bc"},
 ]
 urllib3 = [
     {file = "urllib3-1.25.7-py2.py3-none-any.whl", hash = "sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293"},
diff --git a/pyproject.toml b/pyproject.toml
index 9065066e24063dde8042828c88bc814afc7fa639..45e06f206c94d9da5035321b0dd4f5e4cc02044e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -20,6 +20,7 @@ classifiers = [
 
 [tool.poetry.dependencies]
 python = "^3.7"
+calendarweek = "^0.4.4"
 AlekSIS = { path = "../../.." }
 
 [build-system]