diff --git a/aleksis/apps/chronos/admin.py b/aleksis/apps/chronos/admin.py
new file mode 100644
index 0000000000000000000000000000000000000000..b43af26cb5d602b1e5584e2be32f6adf2f2294fe
--- /dev/null
+++ b/aleksis/apps/chronos/admin.py
@@ -0,0 +1,5 @@
+from django.contrib import admin
+
+from .models import TimetableWidget
+
+admin.site.register(TimetableWidget)
diff --git a/aleksis/apps/chronos/migrations/0001_initial.py b/aleksis/apps/chronos/migrations/0001_initial.py
index 28eab760977e1f3290581cf1930a09a1c2ad7fc5..a5273c7889a7d9d4fa9eaeadb0e144f9e9ff1a28 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.weeks
+import aleksis.apps.chronos.util.date
 import aleksis.core.util.core_helpers
 
 
@@ -229,7 +229,7 @@ class Migration(migrations.Migration):
                 (
                     "week",
                     models.IntegerField(
-                        default=aleksis.apps.chronos.util.weeks.CalendarWeek.current_week,
+                        default=aleksis.apps.chronos.util.date.CalendarWeek.current_week,
                         verbose_name="Week",
                     ),
                 ),
diff --git a/aleksis/apps/chronos/model_extensions.py b/aleksis/apps/chronos/model_extensions.py
index 8f16b828ae522f64daa3df7371871c8afcc4a0c3..672600908bbb9d847ce8fae762ca5b1dd5da4b9b 100644
--- a/aleksis/apps/chronos/model_extensions.py
+++ b/aleksis/apps/chronos/model_extensions.py
@@ -1,4 +1,6 @@
-from aleksis.core.models import Person
+from typing import Optional, Union
+
+from aleksis.core.models import Person, Group
 
 from .models import Lesson, LessonPeriod
 
@@ -10,6 +12,32 @@ def is_teacher(self):
     return self.lesson_periods_as_teacher.exists()
 
 
+@Person.property
+def timetable_type(self) -> Optional[str]:
+    """ Return which type of timetable this user has """
+
+    if self.is_teacher:
+        return "teacher"
+    elif self.primary_group:
+        return "group"
+    else:
+        return None
+
+
+@Person.property
+def timetable_object(self) -> Optional[Union[Group, Person]]:
+    """ Return the object which has the user's timetable """
+
+    type_ = self.timetable_type
+
+    if type_ == "teacher":
+        return self
+    elif type_ == "group":
+        return self.primary_group
+    else:
+        return None
+
+
 @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 8cfdb3fec8e2f10f9bd4636374804f86deb3622c..5a6eb38f9bf4b308e0029506700751322a1a249e 100644
--- a/aleksis/apps/chronos/models.py
+++ b/aleksis/apps/chronos/models.py
@@ -1,5 +1,6 @@
 from __future__ import annotations
 
+from collections import OrderedDict
 from datetime import date, datetime, timedelta, time
 from typing import Dict, Optional, Tuple, Union
 
@@ -8,6 +9,7 @@ from django.core.exceptions import ValidationError
 from django.db import models
 from django.db.models import F, Max, Min, Q
 from django.db.models.functions import Coalesce
+from django.forms import Media
 from django.http.request import QueryDict
 from django.urls import reverse
 from django.utils import timezone
@@ -15,11 +17,13 @@ from django.utils.decorators import classproperty
 from django.utils.translation import ugettext_lazy as _
 
 from calendarweek.django import CalendarWeek, i18n_day_names_lazy, i18n_day_abbrs_lazy
+from django_global_request.middleware import get_request
 
 from aleksis.core.mixins import ExtensibleModel
-from aleksis.core.models import Group, Person
+from aleksis.core.models import Group, Person, DashboardWidget
 
-from aleksis.apps.chronos.util.weeks import week_weekday_from_date
+from aleksis.apps.chronos.util.date import week_weekday_from_date
+from aleksis.core.util.core_helpers import has_person
 
 
 class LessonPeriodManager(models.Manager):
@@ -202,6 +206,41 @@ class LessonPeriodQuerySet(LessonDataQuerySet):
         else:
             return None
 
+    def filter_from_person(self, person: Person) -> Optional[models.QuerySet]:
+        type_ = person.timetable_type
+
+        if type_ == "teacher":
+            # Teacher
+
+            return person.lesson_periods_as_teacher
+
+        elif type_ == "group":
+            # Student
+
+            return person.lesson_periods_as_participant
+
+        else:
+            # If no student or teacher
+            return None
+
+    def daily_lessons_for_person(self, person: Person, wanted_day: date) -> Optional[models.QuerySet]:
+        lesson_periods = LessonPeriod.objects.filter_from_person(person)
+
+        if lesson_periods is None:
+            return None
+
+        return lesson_periods.on_day(wanted_day)
+
+    def per_period_one_day(self) -> OrderedDict:
+        """ Group selected lessons per period for one day """
+        per_period = {}
+        for lesson_period in self:
+            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]
+        return OrderedDict(sorted(per_period.items()))
+
 
 class LessonSubstitutionQuerySet(LessonDataQuerySet):
     _period_path = "lesson_period__"
@@ -505,3 +544,40 @@ class LessonPeriod(ExtensibleModel):
     class Meta:
         ordering = ["lesson__date_start", "period__weekday", "period__period"]
         indexes = [models.Index(fields=["lesson", "period"])]
+
+
+class TimetableWidget(DashboardWidget):
+    template = "chronos/widget.html"
+
+    def get_context(self):
+        request = get_request()
+        context = {"has_plan": True}
+        wanted_day = TimePeriod.get_next_relevant_day(timezone.now().date(), datetime.now().time())
+
+        if has_person(request.user):
+            person = request.user.person
+
+            lesson_periods = LessonPeriod.objects.daily_lessons_for_person(person, wanted_day)
+            type_ = person.timetable_type
+
+            if type_ is None:
+                # If no student or teacher, redirect to all timetables
+                context["has_plan"] = False
+            else:
+                context["lesson_periods"] = lesson_periods.per_period_one_day()
+                context["type"] = type_
+                context["day"] = wanted_day
+                context["periods"] = TimePeriod.get_times_dict()
+                context["smart"] = True
+        else:
+            context["has_plan"] = False
+
+        return context
+
+    media = Media(css={
+        "all": ("css/chronos/timetable.css",)
+    })
+
+    class Meta:
+        proxy = True
+        verbose_name = _("Timetable widget")
diff --git a/aleksis/apps/chronos/templates/chronos/my_timetable.html b/aleksis/apps/chronos/templates/chronos/my_timetable.html
index 90adf8fb4a2f0c04eeb605ae7ff6b271a6ab6141..d508fd43b0b02009c7124e5bb03c4bde2b77e8e5 100644
--- a/aleksis/apps/chronos/templates/chronos/my_timetable.html
+++ b/aleksis/apps/chronos/templates/chronos/my_timetable.html
@@ -50,18 +50,9 @@
 
         </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 %}
+      {% include "chronos/partials/lessons_col.html" with lesson_periods=lesson_periods %}
 
     </div>
   </div>
diff --git a/aleksis/apps/chronos/templates/chronos/partials/lessons_col.html b/aleksis/apps/chronos/templates/chronos/partials/lessons_col.html
new file mode 100644
index 0000000000000000000000000000000000000000..abb2710a6a147d2bbc67ab17be784a6c52f5da69
--- /dev/null
+++ b/aleksis/apps/chronos/templates/chronos/partials/lessons_col.html
@@ -0,0 +1,10 @@
+{% 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">
+      {% include "chronos/partials/lesson.html" with lessons=lessons %}
+    </div>
+  </div>
+{% endfor %}
diff --git a/aleksis/apps/chronos/templates/chronos/widget.html b/aleksis/apps/chronos/templates/chronos/widget.html
new file mode 100644
index 0000000000000000000000000000000000000000..7c4e112bd4c599d8e93df363588005467379bde3
--- /dev/null
+++ b/aleksis/apps/chronos/templates/chronos/widget.html
@@ -0,0 +1,32 @@
+{# -*- engine:django -*- #}
+
+{% load i18n static humanize %}
+
+<div class="card">
+  <div class="card-content">
+    <span class="card-title">
+      {% blocktrans with day=day|naturalday:"l" %}
+        My timetable for {{ day }}
+      {% endblocktrans %}
+    </span>
+    <div class="timetable-plan">
+      {% if has_plan %}
+        {% include "chronos/partials/lessons_col.html" with lesson_periods=lesson_periods %}
+      {% else %}
+        <div class="alert warning">
+          <p>
+            <i class="material-icons left">info</i>
+            {% blocktrans %}
+              There is no timetable linked to your person.
+            {% endblocktrans %}
+          </p>
+        </div>
+      {% endif %}
+    </div>
+  </div>
+  {% if has_plan %}
+    <div class="card-action">
+      <a href="{% url "my_timetable" %}">{% trans "Go to smart plan" %}</a>
+    </div>
+  {% endif %}
+</div>
diff --git a/aleksis/apps/chronos/templatetags/week_helpers.py b/aleksis/apps/chronos/templatetags/week_helpers.py
index 26dee1e900e84367e8ec4b1efbcdd8c6d298499e..acfb3a3a8859cc50c9e250520d9bcb32f3764ebe 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 aleksis.apps.chronos.util.weeks import CalendarWeek, week_period_to_date, week_weekday_to_date
+from aleksis.apps.chronos.util.date import CalendarWeek, week_period_to_date, week_weekday_to_date
 
 register = template.Library()
 
diff --git a/aleksis/apps/chronos/util/weeks.py b/aleksis/apps/chronos/util/date.py
similarity index 85%
rename from aleksis/apps/chronos/util/weeks.py
rename to aleksis/apps/chronos/util/date.py
index 32ec8b81f006d0332b5be8b1502043a1c1806766..f17aa0ba8354b9dce1ed9db5ee158954afc71ea0 100644
--- a/aleksis/apps/chronos/util/weeks.py
+++ b/aleksis/apps/chronos/util/date.py
@@ -2,6 +2,9 @@ from datetime import date
 from typing import Tuple, List, Union
 
 from calendarweek import CalendarWeek
+from calendarweek.django import i18n_day_names
+from django.utils import timezone
+from django.utils.translation import gettext_lazy as _
 
 
 def week_weekday_from_date(when: date) -> Tuple[CalendarWeek, int]:
diff --git a/aleksis/apps/chronos/views.py b/aleksis/apps/chronos/views.py
index d885886ee35ed22f9b0690fa627a9d100cf190cf..daad66d7c699cfd95d711ad9faa2760274fe8049 100644
--- a/aleksis/apps/chronos/views.py
+++ b/aleksis/apps/chronos/views.py
@@ -19,7 +19,7 @@ from .forms import LessonSubstitutionForm
 from .models import LessonPeriod, LessonSubstitution, TimePeriod, Room
 from .tables import LessonsTable
 from .util.js import date_unix
-from .util.weeks import CalendarWeek, get_weeks_for_year
+from .util.date import CalendarWeek, get_weeks_for_year
 from aleksis.core.util.core_helpers import has_person
 
 
@@ -62,46 +62,29 @@ def my_timetable(
     if has_person(request.user):
         person = request.user.person
 
-        if person.is_teacher:
-            # Teacher
+        lesson_periods = LessonPeriod.objects.daily_lessons_for_person(person, wanted_day)
 
-            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 lesson_periods is None:
             # 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]
+        type_ = person.timetable_type
+        super_el = person.timetable_object
 
-    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
+        context["lesson_periods"] = lesson_periods.per_period_one_day()
+        context["super"] = {"type": type_, "el": super_el}
+        context["type"] = type_
+        context["day"] = wanted_day
+        context["periods"] = TimePeriod.get_times_dict()
+        context["smart"] = True
 
-    context["url_prev"], context["url_next"] = TimePeriod.get_prev_next_by_day(
-        wanted_day, "my_timetable_by_date"
-    )
+        context["url_prev"], context["url_next"] = TimePeriod.get_prev_next_by_day(
+            wanted_day, "my_timetable_by_date"
+        )
 
-    return render(request, "chronos/my_timetable.html", context)
+        return render(request, "chronos/my_timetable.html", context)
+    else:
+        return redirect("all_timetables")
 
 
 @login_required