diff --git a/apps/official/BiscuIT-App-Alsijil b/apps/official/BiscuIT-App-Alsijil
index a9df90013aa7330fc2917517f8859f35dc950ebb..7a51426bc1219837893af2766ce8c7f9fab296f2 160000
--- a/apps/official/BiscuIT-App-Alsijil
+++ b/apps/official/BiscuIT-App-Alsijil
@@ -1 +1 @@
-Subproject commit a9df90013aa7330fc2917517f8859f35dc950ebb
+Subproject commit 7a51426bc1219837893af2766ce8c7f9fab296f2
diff --git a/apps/official/BiscuIT-App-Chronos b/apps/official/BiscuIT-App-Chronos
index 5e8efdcbb326e4b19ed58fd1d1b1e0d995e95882..e96f8a231fe363b568a2809e92ddb54e83deceff 160000
--- a/apps/official/BiscuIT-App-Chronos
+++ b/apps/official/BiscuIT-App-Chronos
@@ -1 +1 @@
-Subproject commit 5e8efdcbb326e4b19ed58fd1d1b1e0d995e95882
+Subproject commit e96f8a231fe363b568a2809e92ddb54e83deceff
diff --git a/apps/official/BiscuIT-App-Exlibris b/apps/official/BiscuIT-App-Exlibris
index ad8af3fe185217a5d95a7880d7d594089ad818b7..86d3a0a2d95541e1901e5dd372d46cfd9323a08d 160000
--- a/apps/official/BiscuIT-App-Exlibris
+++ b/apps/official/BiscuIT-App-Exlibris
@@ -1 +1 @@
-Subproject commit ad8af3fe185217a5d95a7880d7d594089ad818b7
+Subproject commit 86d3a0a2d95541e1901e5dd372d46cfd9323a08d
diff --git a/apps/official/BiscuIT-App-SchILD-NRW b/apps/official/BiscuIT-App-SchILD-NRW
index ef6fed8b6eb58bf855eba9828c248caeb9f94357..f2a41d5b4e66aafc00d9a7487bb49c337a97049f 160000
--- a/apps/official/BiscuIT-App-SchILD-NRW
+++ b/apps/official/BiscuIT-App-SchILD-NRW
@@ -1 +1 @@
-Subproject commit ef6fed8b6eb58bf855eba9828c248caeb9f94357
+Subproject commit f2a41d5b4e66aafc00d9a7487bb49c337a97049f
diff --git a/apps/official/BiscuIT-App-Untis b/apps/official/BiscuIT-App-Untis
index 50638fe23de3f003e51460fd42604bd1f2e92764..0c78a36be79b6171c4c6d287387a0173ae513f2e 160000
--- a/apps/official/BiscuIT-App-Untis
+++ b/apps/official/BiscuIT-App-Untis
@@ -1 +1 @@
-Subproject commit 50638fe23de3f003e51460fd42604bd1f2e92764
+Subproject commit 0c78a36be79b6171c4c6d287387a0173ae513f2e
diff --git a/biscuit/core/apps.py b/biscuit/core/apps.py
index b2afdd550c2eee96a5266775b847901067fa5be5..844c9ad3e2118f0f1175f2ec3f9c051a289ddbdc 100644
--- a/biscuit/core/apps.py
+++ b/biscuit/core/apps.py
@@ -10,7 +10,7 @@ class CoreConfig(AppConfig):
     name = 'biscuit.core'
     verbose_name = _('BiscuIT - The Free School Information System')
 
-    def clean_scss(self):
+    def clean_scss(self) -> None:
         for source_map in glob(os.path.join(settings.STATIC_ROOT, '*.css.map')):
             try:
                 os.unlink(source_map)
@@ -18,5 +18,5 @@ class CoreConfig(AppConfig):
                 # Ignore because old is better than nothing
                 pass  # noqa
 
-    def ready(self):
+    def ready(self) -> None:
         self.clean_scss()
diff --git a/biscuit/core/decorators.py b/biscuit/core/decorators.py
index 1881f24624a168299a5bdec18ad76998eeaf0b3d..732f120958924f683f05482bd57661cc503f2882 100644
--- a/biscuit/core/decorators.py
+++ b/biscuit/core/decorators.py
@@ -1,7 +1,8 @@
+from typing import Callable
 from django.contrib.auth.decorators import user_passes_test
 
 
-def admin_required(function=None):
+def admin_required(function: Callable = None) -> Callable:
     actual_decorator = user_passes_test(
         lambda u: u.is_active and u.is_superuser)
     return actual_decorator(function)
diff --git a/biscuit/core/mixins.py b/biscuit/core/mixins.py
index f5fcc947b83a97f0db66595a117dde88f054a07c..3fa40c9b79ae7b2461d5e6b33ec2c40267924a18 100644
--- a/biscuit/core/mixins.py
+++ b/biscuit/core/mixins.py
@@ -4,7 +4,7 @@ from .util.core_helpers import get_current_school
 
 
 class SchoolRelatedManager(models.Manager):
-    def get_queryset(self):
+    def get_queryset(self) -> models.query.QuerySet:
         qs = super().get_queryset()
         school = get_current_school()
 
diff --git a/biscuit/core/models.py b/biscuit/core/models.py
index 78421522874b32975c9845693158727d4e0d6d79..7839c0e6b9ce468733abab4f1c8b10832667007a 100644
--- a/biscuit/core/models.py
+++ b/biscuit/core/models.py
@@ -76,7 +76,7 @@ class Person(SchoolRelated):
 
     primary_group = models.ForeignKey('Group', models.SET_NULL, null=True)
 
-    def __str__(self):
+    def __str__(self) -> str:
         return '%s, %s' % (self.last_name, self.first_name)
 
 
@@ -96,5 +96,5 @@ class Group(SchoolRelated):
     members = models.ManyToManyField('Person', related_name='member_of')
     owners = models.ManyToManyField('Person', related_name='owner_of')
 
-    def __str__(self):
+    def __str__(self) -> str:
         return '%s (%s)' % (self.name, self.short_name)
diff --git a/biscuit/core/tables.py b/biscuit/core/tables.py
index f7fbeb93a7ecab450d6cc3d4061ea92c0dc56c58..0b57e2b11efd27a4cd7a1269b810efe134816750 100644
--- a/biscuit/core/tables.py
+++ b/biscuit/core/tables.py
@@ -10,6 +10,7 @@ class PersonsTable(tables.Table):
     first_name = tables.LinkColumn('person_by_id', args=[A('id')])
     last_name = tables.LinkColumn('person_by_id', args=[A('id')])
 
+
 class GroupsTable(tables.Table):
     class Meta:
         attrs = {'class': 'table table-striped table-bordered table-hover table-responsive-xl'}
diff --git a/biscuit/core/templatetags/data_helpers.py b/biscuit/core/templatetags/data_helpers.py
index 8f28bcc95013afe704b6db0d831e2acf139a15fc..f5fb6a56f6f1b37b3fca026679f38d0d25ead9cb 100644
--- a/biscuit/core/templatetags/data_helpers.py
+++ b/biscuit/core/templatetags/data_helpers.py
@@ -1,8 +1,10 @@
+from typing import Dict, Any
+
 from django import template
 
 register = template.Library()
 
 
 @register.filter
-def get_dict(value, arg):
+def get_dict(value: Dict[Any, Any], arg: Any) -> Any:
     return value[arg]
diff --git a/biscuit/core/util/core_helpers.py b/biscuit/core/util/core_helpers.py
index d4bb3e38056edbe881789ba7c191d16f22f2169b..94ffde727a44c9eb516ef3b42cac38d8b2377ae3 100644
--- a/biscuit/core/util/core_helpers.py
+++ b/biscuit/core/util/core_helpers.py
@@ -1,11 +1,13 @@
 from importlib import import_module
 import pkgutil
-from typing import Sequence
+from typing import Optional, Sequence
 
 from django_global_request.middleware import get_request
 
+from ..models import School
 
-def get_app_packages() -> Sequence:
+
+def get_app_packages() -> Sequence[str]:
     """ Find all packages within the biscuit.apps namespace. """
 
     # Import error are non-fatal here because probably simply no app is installed.
@@ -29,7 +31,7 @@ def get_app_packages() -> Sequence:
     return pkgs
 
 
-def get_current_school():
+def get_current_school() -> Optional[School]:
     request = get_request()
 
     if request:
diff --git a/biscuit/core/util/messages.py b/biscuit/core/util/messages.py
index 7a1b35e010bed45b7fc89c3d277a240b101a7658..98a273b90eab32a9de5961a5542355f2acbfebe0 100644
--- a/biscuit/core/util/messages.py
+++ b/biscuit/core/util/messages.py
@@ -1,30 +1,32 @@
 import logging
+from typing import Optional
 
 from django.contrib import messages
+from django.http import HttpRequest
 
 
-def add_message(request, level, message, **kwargs):
+def add_message(request: Optional[HttpRequest], level: int, message: str, **kwargs) -> Any:
     if request:
         return messages.add_message(request, level, message, **kwargs)
     else:
         return logging.getLogger(__name__).log(level, message)
 
 
-def debug(request, message, **kwargs):
+def debug(request: Optional[HttpRequest], message: str, **kwargs) -> Any
     return add_message(request, messages.DEBUG, message, **kwargs)
 
 
-def info(request, message, **kwargs):
+def info(request: Optional[HttpRequest], message: str, **kwargs) -> Any
     return add_message(request, messages.INFO, message, **kwargs)
 
 
-def success(request, message, **kwargs):
+def success(request: Optional[HttpRequest], message: str, **kwargs) -> Any
     return add_message(request, messages.SUCCESS, message, **kwargs)
 
 
-def warning(request, message, **kwargs):
+def warning(request: Optional[HttpRequest], message: str, **kwargs) -> Any
     return add_message(request, messages.WARNING, message, **kwargs)
 
 
-def error(request, message, **kwargs):
+def error(request: Optional[HttpRequest], message: str, **kwargs) -> Any
     return add_message(request, messages.ERROR, message, **kwargs)
diff --git a/biscuit/core/util/sass_helpers.py b/biscuit/core/util/sass_helpers.py
index ed864d07f5d440c9413a721415982cb52e38b276..aa28accf32e4cbd42711c7b69ccc2bf8e8dfbc22 100644
--- a/biscuit/core/util/sass_helpers.py
+++ b/biscuit/core/util/sass_helpers.py
@@ -1,7 +1,8 @@
 from colour import web2hex
 from sass import SassColor
 
-def get_colour(html_colour):
+
+def get_colour(html_colour: str) -> SassColor:
     rgb = web2hex(html_colour, force_long=True)[1:]
     r, g, b = int(rgb[0:2], 16), int(rgb[2:4], 16), int(rgb[4:6], 16)
 
diff --git a/biscuit/core/views.py b/biscuit/core/views.py
index e56a0ddd4bcaa1241b630bc932b0e619011e66a6..b4a4d6635468c59b628b7189ed9c090b985919ca 100644
--- a/biscuit/core/views.py
+++ b/biscuit/core/views.py
@@ -1,6 +1,6 @@
 from django.contrib.auth.decorators import login_required
 from django.conf import settings
-from django.http import Http404
+from django.http import Http404, HttpRequest, HttpResponse
 from django.shortcuts import render
 from django_tables2 import RequestConfig
 from django.utils.translation import ugettext_lazy as _
@@ -8,12 +8,13 @@ from .models import Person, Group
 from .tables import PersonsTable, GroupsTable
 
 
-def index(request):
+def index(request: HttpRequest) -> HttpResponse:
     context = {}
     return render(request, 'core/index.html', context)
 
-def error_handler(status):
-    def real_handler(request, *args, **kwargs):
+
+def error_handler(status: int) -> Callable[..., HttpResponse]:
+    def real_handler(request: HttpRequest, *args, **kwargs) -> HttpResponse:
         context = {}
 
         context['status'] = status
@@ -29,8 +30,9 @@ def error_handler(status):
 
     return real_handler
 
+
 @login_required
-def persons(request):
+def persons(request: HttpRequest) -> HttpResponse:
     context = {}
 
     # Get all persons
@@ -45,7 +47,7 @@ def persons(request):
 
 
 @login_required
-def person(request, id_, template):
+def person(request: HttpRequest, id_: int, template: str) -> HttpResponse:
     context = {}
 
     # Get person and check access
@@ -67,8 +69,9 @@ def person(request, id_, template):
 
     return render(request, 'core/person_%s.html' % template, context)
 
+
 @login_required
-def group(request, id_, template):
+def group(request: HttpRequest, id_: int, template: str) -> HttpResponse:
     context = {}
 
     # Get group and check if it exist
@@ -93,8 +96,9 @@ def group(request, id_, template):
 
     return render(request, 'core/group_%s.html' % template, context)
 
+
 @login_required
-def groups(request):
+def groups(request: HttpRequest) -> HttpResponse:
     context = {}
 
     # Get all groups