diff --git a/INSTALL.rst b/INSTALL.rst
index c628b58..3678c1e 100644
--- a/INSTALL.rst
+++ b/INSTALL.rst
@@ -18,7 +18,7 @@ Prerequisites
 
 You need the following libraries and/or programs:
 
-* `Python`_ - check the ``Dockerfile`` for the required version.
+* `Python`_ - 3.11
 * Python `Virtualenv`_ and `Pip`_
 * `PostgreSQL`_
 * `Node.js`_
@@ -44,13 +44,10 @@ development machine.
 
    .. code-block:: bash
 
-       $ git clone git@bitbucket.org:maykinmedia/referentielijsten.git
+       $ git clone https://github.com/maykinmedia/referentielijsten.git
        $ cd referentielijsten
 
-3. Install all required (backend) libraries.
-   **Tip:** You can use the ``bootstrap.py`` script to install the requirements
-   and set the proper settings in ``manage.py``. Or, perform the steps
-   manually:
+3. Install all required (backend) libraries:
 
    .. code-block:: bash
 
@@ -69,6 +66,7 @@ development machine.
 
    .. code-block:: bash
 
+       $ source env/bin/activate
        $ python src/manage.py collectstatic --link
        $ python src/manage.py migrate
 
@@ -148,10 +146,6 @@ file or as part of the ``(post)activate`` of your virtualenv.
 * ``DB_HOST``: database host. Defaults to ``localhost``
 * ``DB_PORT``: database port. Defaults to ``5432``.
 
-* ``SENTRY_DSN``: the DSN of the project in Sentry. If set, enabled Sentry SDK as
-  logger and will send errors/logging to Sentry. If unset, Sentry SDK will be
-  disabled.
-
 Docker
 ======
 
@@ -162,7 +156,7 @@ The easiest way to get the project started is by using `Docker Compose`_.
 
    .. code-block:: bash
 
-       $ git clone git@bitbucket.org:maykinmedia/referentielijsten.git
+       $ git clone https://github.com/maykinmedia/referentielijsten.git
        Cloning into 'referentielijsten'...
        ...
 
@@ -194,8 +188,8 @@ The easiest way to get the project started is by using `Docker Compose`_.
        ...
        Superuser created successfully.
 
-       $ docker exec -it referentielijsten_web_1 /app/src/manage.py loaddata admin_index groups
-       Installed 5 object(s) from 2 fixture(s)
+       $ docker exec -it referentielijsten_web_1 /app/src/manage.py loaddata default_admin_index.json
+       Installed 4 object(s) from 1 fixture(s)
 
 4. Point your browser to ``http://localhost:8000/`` to access the project's
    management interface with the credentials used in step 3.
@@ -240,60 +234,6 @@ all settings.
 
     $ docker exec -it referentielijsten /app/src/manage.py createsuperuser
 
-Building and publishing the image
----------------------------------
-
-Using ``bin/release-docker-image``, you can easily build and tag the image.
-
-The script is based on git branches and tags - if you're on the ``master``
-branch and the current ``HEAD`` is tagged, the tag will be used as
-``RELEASE_TAG`` and the image will be pushed. If you want to push the image
-without a git tag, you can use the ``RELEASE_TAG`` envvar.
-
-The image will only be pushed if the ``JOB_NAME`` envvar is set. The image
-will always be built, even if no envvar is set. The default release tag is
-``latest``.
-
-Example usage:
-
-.. code-block:: bash
-
-    JOB_NAME=publish RELEASE_TAG=dev ./bin/release-docker-image.sh
-
-
-Staging and production
-======================
-
-Ansible is used to deploy test, staging and production servers. It is assumed
-the target machine has a clean `Debian`_ installation.
-
-1. Make sure you have `Ansible`_ installed (globally or in the virtual
-   environment):
-
-   .. code-block:: bash
-
-       $ pip install ansible
-
-2. Navigate to the project directory, and install the Maykin deployment
-   submodule if you haven't already:
-
-   .. code-block:: bash
-
-       $ git submodule update --init
-
-3. Run the Ansible playbook to provision a clean Debian machine:
-
-   .. code-block:: bash
-
-       $ cd deployment
-       $ ansible-playbook <test/staging/production>.yml
-
-For more information, see the ``README`` file in the deployment directory.
-
-.. _Debian: https://www.debian.org/
-.. _Ansible: https://pypi.org/project/ansible/
-
-
 Settings
 ========
 
diff --git a/README.rst b/README.rst
index ee0d0d2..6cdde01 100644
--- a/README.rst
+++ b/README.rst
@@ -3,15 +3,15 @@ referentielijsten
 ==================
 
 :Version: 0.1.0
-:Source: https://bitbucket.org/maykinmedia/referentielijsten
-:Keywords: ``<keywords>``
+:Source: https://github.com/maykinmedia/referentielijsten
+:Keywords: referentielijsten, stambomen
 :PythonVersion: 3.11
 
-|build-status| |requirements|
+|docker|
 
 ``<oneliner describing the project>``
 
-Developed by `Maykin Media B.V.`_ for ``<client>``
+Developed by `Maykin Media B.V.`_
 
 
 Introduction
@@ -19,12 +19,50 @@ Introduction
 
 ``<describe the project in a few paragraphs and briefly mention the features>``
 
+API specificatie
+================
 
-Documentation
-=============
+Hieronder staat de versie van Open Klant en welke versie van de 
+API-specificatie wordt aangeboden.
 
-See ``INSTALL.rst`` for installation instructions, available settings and
-commands.
+==========================  ==============  =============   ================
+Referentielijsten versie    API versie      Release datum   API specificatie
+==========================  ==============  =============   ================
+master/latest               n/a             n/a             `ReDoc <https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/maykinmedia/referentielijsten/master/src/api/openapi.yaml>`_,
+                                                            `Swagger <https://petstore.swagger.io/?url=https://raw.githubusercontent.com/maykinmedia/referentielijsten/master/src/api/openapi.yaml>`_
+
+
+Ready-to-go implementatie
+=========================
+
+|build-status| |coverage| |code-style| |codeql| |black| |python-versions|
+
+Deze implementatie is bedoeld als referentie implementatie van de API
+specificaties maar tevens een productiewaardig component dat ingezet kan worden
+in het ICT landschap van de overheid.
+
+Quickstart
+----------
+
+1. Download en start Open Klant:
+
+   .. code:: bash
+
+      $ wget https://raw.githubusercontent.com/maykinmedia/referentielijsten/master/docker-compose.yml
+      $ docker-compose up -d --no-build
+      $ docker-compose exec web src/manage.py createsuperuser
+
+2. In de browser, navigeer naar ``http://localhost:8000/`` om de beheerinterface
+   en de API te benaderen.
+
+
+Links
+=====
+
+* `Docker image <https://hub.docker.com/r/maykinmedia/referentielijsten>`_
+* `Issues <https://github.com/maykinmedia/referentielijsten/issues>`_
+* `Code <https://github.com/maykinmedia/referentielijsten>`_
+* `Community <https://commonground.nl/groups/view/6bca7599-0f58-44e4-a405-7aa3a4c682f3/referentielijsten>`_
 
 
 References
@@ -34,13 +72,35 @@ References
 * `Code <https://bitbucket.org/maykinmedia/referentielijsten>`_
 
 
-.. |build-status| image:: https://github.com/maykinmedia/referentielijsten/workflows/ci/badge.svg?branch=master
+.. _`Maykin B.V.`: https://www.maykinmedia.nl
+
+.. |build-status| image:: https://github.com/maykinmedia/referentielijsten/workflows/ci.yml/badge.svg?branch=master
     :alt: Build status
     :target: https://github.com/maykinmedia/referentielijsten/actions?query=workflow%3Aci
 
-.. |requirements| image:: https://requires.io/bitbucket/maykinmedia/referentielijsten/requirements.svg?branch=master
-     :target: https://requires.io/bitbucket/maykinmedia/referentielijsten/requirements/?branch=master
-     :alt: Requirements status
+.. |coverage| image:: https://codecov.io/github/maykinmedia/referentielijsten/branch/master/graphs/badge.svg?branch=master
+    :alt: Coverage
+    :target: https://codecov.io/gh/maykinmedia/referentielijsten
+
+.. |code-style| image:: https://github.com/maykinmedia/referentielijsten/actions/workflows/code-style.yml/badge.svg?branch=master
+    :alt: Code style
+    :target: https://github.com/maykinmedia/referentielijsten/actions/workflows/code-style.yml
+
+.. |codeql| image:: https://github.com/maykinmedia/referentielijsten/actions/workflows/codeql.yml/badge.svg?branch=master
+    :alt: CodeQL scan
+    :target: https://github.com/maykinmedia/referentielijsten/actions/workflows/codeql.yml
+
+.. |black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
+    :alt: Code style
+    :target: https://github.com/psf/black
+
+.. |docker| image:: https://img.shields.io/docker/v/maykinmedia/referentielijsten?sort=semver
+    :alt: Docker image
+    :target: https://hub.docker.com/r/maykinmedia/referentielijsten
 
+.. |python-versions| image:: https://img.shields.io/badge/python-3.11%2B-blue.svg
+    :alt: Supported Python version
 
-.. _Maykin Media B.V.: https://www.maykinmedia.nl
+.. |lint-oas| image:: https://github.com/maykinmedia/referentielijsten/workflows/actions/lint-oas/badge.svg
+    :alt: Lint OAS
+    :target: https://github.com/maykinmedia/referentielijsten/actions?query=workflow%3Alint-oas
diff --git a/bin/celery_beat.sh b/bin/celery_beat.sh
deleted file mode 100755
index b9bce2b..0000000
--- a/bin/celery_beat.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash
-
-set -e
-
-LOGLEVEL=${CELERY_LOGLEVEL:-INFO}
-
-mkdir -p celerybeat
-
-echo "Starting celery beat"
-exec celery beat \
-    --app referentielijsten \
-    -l $LOGLEVEL \
-    --workdir src \
-    -s ../celerybeat/beat
diff --git a/bin/celery_flower.sh b/bin/celery_flower.sh
deleted file mode 100755
index a90c30c..0000000
--- a/bin/celery_flower.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-exec celery flower --app referentielijsten --workdir src
diff --git a/bin/celery_worker.sh b/bin/celery_worker.sh
deleted file mode 100755
index 9374a13..0000000
--- a/bin/celery_worker.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-
-set -e
-
-LOGLEVEL=${CELERY_LOGLEVEL:-INFO}
-CONCURRENCY=${CELERY_WORKER_CONCURRENCY:-1}
-
-QUEUE=${1:-${CELERY_WORKER_QUEUE:=celery}}
-WORKER_NAME=${2:-${CELERY_WORKER_NAME:="${QUEUE}"@%n}}
-
-echo "Starting celery worker $WORKER_NAME with queue $QUEUE"
-exec celery worker \
-    --app referentielijsten \
-    -Q $QUEUE \
-    -n $WORKER_NAME \
-    -l $LOGLEVEL \
-    --workdir src \
-    -O fair \
-    -c $CONCURRENCY
-
diff --git a/src/referentielijsten/api/openapi.yaml b/src/referentielijsten/api/openapi.yaml
index e3218c5..fe947a1 100644
--- a/src/referentielijsten/api/openapi.yaml
+++ b/src/referentielijsten/api/openapi.yaml
@@ -32,6 +32,7 @@ paths:
           type: string
         description: 'De waarde van de `tabel__code` die gelinkt is aan de items:
           VERPLICHT'
+        required: true
       tags:
       - items
       security:
@@ -47,13 +48,13 @@ paths:
           content:
             application/json:
               schema:
-                $ref: '#/components/schemas/ValidationError'
+                $ref: '#/components/schemas/FieldValidationError'
               examples:
                 Tabel_codeQueryParamNotProvided:
                   value:
                     name: tabel__code
-                    code: invalid
-                    reason: Verplichte query parameter `tabel__code` niet mee gegeven.
+                    code: required
+                    reason: Dit veld is vereist.
                   summary: tabel__code query param not provided
           description: ''
   /api/v1/tabellen:
@@ -123,6 +124,23 @@ components:
           type: string
           description: De organisatie naam van de beheerder van dit tabel.
           maxLength: 200
+    FieldValidationError:
+      type: object
+      description: Formaat van validatiefouten.
+      properties:
+        name:
+          type: string
+          description: Naam van het veld met ongeldige gegevens
+        code:
+          type: string
+          description: Systeemcode die het type fout aangeeft
+        reason:
+          type: string
+          description: Uitleg wat er precies fout is met de gegevens
+      required:
+      - code
+      - name
+      - reason
     Item:
       type: object
       properties:
@@ -152,6 +170,9 @@ components:
       - naam
     PaginatedItemList:
       type: object
+      required:
+      - count
+      - results
       properties:
         count:
           type: integer
@@ -172,6 +193,9 @@ components:
             $ref: '#/components/schemas/Item'
     PaginatedTabelList:
       type: object
+      required:
+      - count
+      - results
       properties:
         count:
           type: integer
@@ -214,24 +238,3 @@ components:
       required:
       - code
       - naam
-    ValidationError:
-      type: object
-      description: |-
-        Validation error format, following the NL API Strategy.
-
-        See https://docs.geostandaarden.nl/api/API-Strategie/ and
-        https://docs.geostandaarden.nl/api/API-Strategie-ext/#error-handling-0
-      properties:
-        name:
-          type: string
-          description: Name of the field with invalid data
-        code:
-          type: string
-          description: System code of the type of error
-        reason:
-          type: string
-          description: Explanation of what went wrong with the data
-      required:
-      - code
-      - name
-      - reason
diff --git a/src/referentielijsten/conf/base.py b/src/referentielijsten/conf/base.py
index 7f7930d..8eb4f6d 100644
--- a/src/referentielijsten/conf/base.py
+++ b/src/referentielijsten/conf/base.py
@@ -1,19 +1,20 @@
 import os
-from pathlib import Path
 
 from django.urls import reverse_lazy
 
-import sentry_sdk
-
 from .api import *  # noqa
-from .utils import config, get_sentry_integrations
+from .utils import config
 
 # Build paths inside the project, so further paths can be defined relative to
 # the code root.
 
-DJANGO_PROJECT_DIR = Path(__file__).resolve().parent.parent
+DJANGO_PROJECT_DIR = os.path.abspath(
+    os.path.join(os.path.dirname(__file__), os.path.pardir)
+)
 
-BASE_DIR = DJANGO_PROJECT_DIR.parent.parent
+BASE_DIR = os.path.abspath(
+    os.path.join(DJANGO_PROJECT_DIR, os.path.pardir, os.path.pardir)
+)
 
 #
 # Core Django settings
@@ -117,7 +118,6 @@
     "rest_framework",
     "vng_api_common",
     # Project applications.
-    "referentielijsten",
     "referentielijsten.accounts",
     "referentielijsten.utils",
     "referentielijsten.api",
@@ -148,7 +148,7 @@
 TEMPLATES = [
     {
         "BACKEND": "django.template.backends.django.DjangoTemplates",
-        "DIRS": [DJANGO_PROJECT_DIR / "templates"],
+        "DIRS": [os.path.join(DJANGO_PROJECT_DIR, "templates")],
         "APP_DIRS": False,  # conflicts with explicity specifying the loaders
         "OPTIONS": {
             "context_processors": [
@@ -166,7 +166,7 @@
 WSGI_APPLICATION = "referentielijsten.wsgi.application"
 
 # Translations
-LOCALE_PATHS = (DJANGO_PROJECT_DIR / "conf" / "locale",)
+LOCALE_PATHS = (os.path.join(DJANGO_PROJECT_DIR, "conf", "locale"),)
 
 #
 # SERVING of static and media files
@@ -174,10 +174,10 @@
 
 STATIC_URL = "/static/"
 
-STATIC_ROOT = BASE_DIR / "static"
+STATIC_ROOT = os.path.join(BASE_DIR, "static")
 
 # Additional locations of static files
-STATICFILES_DIRS = [DJANGO_PROJECT_DIR / "static"]
+STATICFILES_DIRS = [os.path.join(DJANGO_PROJECT_DIR, "static")]
 
 # List of finder classes that know how to find static files in
 # various locations.
@@ -186,7 +186,7 @@
     "django.contrib.staticfiles.finders.AppDirectoriesFinder",
 ]
 
-MEDIA_ROOT = BASE_DIR / "media"
+MEDIA_ROOT = os.path.join(BASE_DIR, "media")
 
 MEDIA_URL = "/media/"
 
@@ -211,7 +211,7 @@
 #
 LOG_STDOUT = config("LOG_STDOUT", default=False)
 
-LOGGING_DIR = BASE_DIR / "log"
+LOGGING_DIR = os.path.join(BASE_DIR, "log")
 
 LOGGING = {
     "version": 1,
@@ -247,7 +247,7 @@
         "django": {
             "level": "DEBUG",
             "class": "logging.handlers.RotatingFileHandler",
-            "filename": LOGGING_DIR / "django.log",
+            "filename": os.path.join(LOGGING_DIR, "django.log"),
             "formatter": "verbose",
             "maxBytes": 1024 * 1024 * 10,  # 10 MB
             "backupCount": 10,
@@ -255,7 +255,7 @@
         "project": {
             "level": "DEBUG",
             "class": "logging.handlers.RotatingFileHandler",
-            "filename": LOGGING_DIR / "referentielijsten.log",
+            "filename": os.path.join(LOGGING_DIR, "referentielijsten.log"),
             "formatter": "verbose",
             "maxBytes": 1024 * 1024 * 10,  # 10 MB
             "backupCount": 10,
@@ -263,7 +263,7 @@
         "performance": {
             "level": "INFO",
             "class": "logging.handlers.RotatingFileHandler",
-            "filename": LOGGING_DIR / "performance.log",
+            "filename": os.path.join(LOGGING_DIR, "performance.log"),
             "formatter": "performance",
             "maxBytes": 1024 * 1024 * 10,  # 10 MB
             "backupCount": 10,
@@ -332,7 +332,7 @@
 # FIXTURES
 #
 
-FIXTURE_DIRS = (DJANGO_PROJECT_DIR / "fixtures",)
+FIXTURE_DIRS = (os.path.join(DJANGO_PROJECT_DIR, "fixtures"),)
 
 #
 # Custom settings
@@ -351,7 +351,7 @@
 if "GIT_SHA" in os.environ:
     GIT_SHA = config("GIT_SHA", "")
 # in docker (build) context, there is no .git directory
-elif (BASE_DIR / ".git").exists():
+elif os.path.exists(os.path.join(BASE_DIR, ".git")):
     try:
         import git
     except ImportError:
@@ -440,22 +440,6 @@
     # "mozilla_django_oidc_db.backends.OIDCAuthenticationBackend",
 ]
 
-#
-# SENTRY - error monitoring
-#
-SENTRY_DSN = config("SENTRY_DSN", None)
-
-if SENTRY_DSN:
-    SENTRY_CONFIG = {
-        "dsn": SENTRY_DSN,
-        "release": RELEASE,
-        "environment": ENVIRONMENT,
-    }
-
-    sentry_sdk.init(
-        **SENTRY_CONFIG, integrations=get_sentry_integrations(), send_default_pii=True
-    )
-
 # Elastic APM
 ELASTIC_APM_SERVER_URL = os.getenv("ELASTIC_APM_SERVER_URL", None)
 ELASTIC_APM = {
diff --git a/src/referentielijsten/conf/locale/nl/LC_MESSAGES/django.po b/src/referentielijsten/conf/locale/nl/LC_MESSAGES/django.po
index f513c5c..4ebedc1 100644
--- a/src/referentielijsten/conf/locale/nl/LC_MESSAGES/django.po
+++ b/src/referentielijsten/conf/locale/nl/LC_MESSAGES/django.po
@@ -119,15 +119,6 @@ msgstr "overnemen"
 msgid "Hijack %(username)s"
 msgstr "Inloggen als %(username)s"
 
-#: foobar/templates/samples/pager.html:8 foobar/templates/samples/pager.html:10
-msgid "Previous"
-msgstr "Vorige"
-
-#: foobar/templates/samples/pager.html:16
-#: foobar/templates/samples/pager.html:18
-msgid "Next"
-msgstr "Volgende"
-
 #: foobar/utils/management/commands/clear_cache.py:10
 msgid "Clear given cache only"
 msgstr "Leeg alleen de opgegeven cache"
diff --git a/src/referentielijsten/conf/utils.py b/src/referentielijsten/conf/utils.py
index 53c045f..e766a5c 100644
--- a/src/referentielijsten/conf/utils.py
+++ b/src/referentielijsten/conf/utils.py
@@ -1,7 +1,6 @@
 import logging
 
 from decouple import Csv, config as _config, undefined
-from sentry_sdk.integrations import DidNotEnable, django, redis
 
 logger = logging.getLogger(__name__)
 
@@ -25,23 +24,3 @@ def config(option: str, default=undefined, *args, **kwargs):
     if default is not undefined and default is not None:
         kwargs.setdefault("cast", type(default))
     return _config(option, default=default, *args, **kwargs)
-
-
-def get_sentry_integrations() -> list:
-    """
-    Determine which Sentry SDK integrations to enable.
-    """
-    default = [
-        django.DjangoIntegration(),
-        redis.RedisIntegration(),
-    ]
-    extra = []
-
-    try:
-        from sentry_sdk.integrations import celery
-    except DidNotEnable:  # happens if the celery import fails by the integration
-        pass
-    else:
-        extra.append(celery.CeleryIntegration())
-
-    return [*default, *extra]
diff --git a/src/referentielijsten/fixtures/default_admin_index.json b/src/referentielijsten/fixtures/default_admin_index.json
new file mode 100644
index 0000000..ba03e25
--- /dev/null
+++ b/src/referentielijsten/fixtures/default_admin_index.json
@@ -0,0 +1,102 @@
+[
+    {
+        "model": "admin_index.appgroup",
+        "fields": {
+            "order": 0,
+            "translations": {
+                "en": "Accounts",
+                "nl": "Accounts"
+            },
+            "name": "Accounts",
+            "slug": "accounts",
+            "models": [
+                [
+                    "accounts",
+                    "user"
+                ],
+                [
+                    "auth",
+                    "group"
+                ]
+            ]
+        }
+    },
+    {
+        "model": "admin_index.appgroup",
+        "fields": {
+            "order": 1,
+            "translations": {
+                "en": "Referentielijsten API",
+                "nl": "Referencelists API"
+            },
+            "name": "Referentielijsten API",
+            "slug": "referentielijsten-api",
+            "models": [
+                [
+                    "api",
+                    "tabel"
+                ],
+                [
+                    "api",
+                    "item"
+                ]
+            ]
+        }
+    },
+    {
+        "model": "admin_index.appgroup",
+        "fields": {
+            "order": 2,
+            "translations": {
+                "en": "Logging",
+                "nl": "Logging"
+            },
+            "name": "Logging",
+            "slug": "logging",
+            "models": [
+                [
+                    "axes",
+                    "accessattempt"
+                ],
+                [
+                    "axes",
+                    "accesslog"
+                ],
+                [
+                    "axes",
+                    "accessfailurelog"
+                ]
+            ]
+        }
+    },
+    {
+        "model": "admin_index.appgroup",
+        "fields": {
+            "order": 3,
+            "translations": {
+                "en": "Configuration",
+                "nl": "Configuratie"
+            },
+            "name": "Configuratie",
+            "slug": "configuration",
+            "models": [
+                [
+                    "admin_index",
+                    "appgroup"
+                ],
+                [
+                    "otp_static",
+                    "staticdevice"
+                ],
+                [
+                    "otp_totp",
+                    "totpdevice"
+                ],
+                [
+                    "two_factor_webauthn",
+                    "webauthndevice"
+                ]
+            ]
+        }
+    }
+]
diff --git a/src/referentielijsten/scss/admin/_admin_theme.scss b/src/referentielijsten/scss/admin/_admin_theme.scss
index 00c6923..a567d4e 100644
--- a/src/referentielijsten/scss/admin/_admin_theme.scss
+++ b/src/referentielijsten/scss/admin/_admin_theme.scss
@@ -172,17 +172,10 @@ div.breadcrumbs {
   }
 }
 
-/**
- * Django form related widget
- */
-.related-widget-wrapper {
-  display: inline-block;
-}
-
 /**
  * Help text mouseover
  */
-div.help {
+ div.help {
   cursor: help;
   width: 16px;
   height: 16px;
@@ -192,7 +185,7 @@ div.help {
   background-size: 14px;
   margin-left: 8px !important;
   margin-top: 6px !important;
-  position: absolute;
+  position: relative;
   text-indent: -9999px;
 
   &:hover {
@@ -218,6 +211,19 @@ div.help {
   }
 }
 
+/* Overrides default Django CSS */
+.aligned label + p,
+.aligned label + div.readonly {
+  display: inline-block;
+  margin-left: inherit !important;
+}
+.aligned label + div.help {
+  margin-left: 2px !important;
+}
+div:has(> div.help ) {
+  display: flex;
+}
+
 /* Overrides default Django CSS */
 .aligned label + p,
 .aligned label + div.readonly {
diff --git a/src/referentielijsten/templates/hijack/contrib/admin/button.html b/src/referentielijsten/templates/hijack/contrib/admin/button.html
deleted file mode 100644
index 81118a6..0000000
--- a/src/referentielijsten/templates/hijack/contrib/admin/button.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% load i18n hijack %}
-{% if request.user|can_hijack:another_user %}
-  <button type="button" class="button" data-hijack-user="{{ another_user.pk }}"
-          data-hijack-next="{{ next }}" data-hijack-url="{% url 'hijack:acquire' %}">
-    {% if is_user_admin %}
-      {% trans 'hijack'|upper %}
-    {% else %}
-      {% blocktrans %}Hijack {{ username }}{% endblocktrans %}
-    {% endif %}
-  </button>
-{% endif %}
diff --git a/src/referentielijsten/templates/index.html b/src/referentielijsten/templates/index.html
index 54e6237..1124c5b 100644
--- a/src/referentielijsten/templates/index.html
+++ b/src/referentielijsten/templates/index.html
@@ -25,7 +25,7 @@ <h1 class="title__header">{{ settings.PROJECT_NAME }} API</h1>
     </nav>
 
     <p>
-      <b>Licensed under the <a class="link" href="https://github.com/maykinmedia/objects-api/blob/master/LICENSE.md">
+      <b>Licensed under the <a class="link" href="https://github.com/maykinmedia/referentielijsten/blob/master/LICENSE.md">
         European Union Public License (EUPL) 1.2</a></b>
     </p>
 
diff --git a/src/referentielijsten/templates/samples/menu.html b/src/referentielijsten/templates/samples/menu.html
deleted file mode 100644
index 9b25670..0000000
--- a/src/referentielijsten/templates/samples/menu.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<nav class="menu">
-    <ul class="menu__list" role="menu">
-        <li class="menu__list-item"><a class="menu__link" href="#">Home</a></li>
-        <li class="menu__list-item"><a class="menu__link" href="#">Page 1</a></li>
-        <li class="menu__list-item"><a class="menu__link" href="#">Page 2</a></li>
-        <li class="menu__list-item"><a class="menu__link" href="#">Page 3</a></li>
-        <li class="menu__list-item"><a class="menu__link" href="#">Page 4</a></li>
-
-        <li class="menu__list-item menu__list-item--right">
-            <a class="menu__link" href="{% url 'admin:index' %}">admin</a>
-        </li>
-    </ul>
-</nav>
diff --git a/src/referentielijsten/templates/samples/pager.html b/src/referentielijsten/templates/samples/pager.html
deleted file mode 100644
index 1de51f6..0000000
--- a/src/referentielijsten/templates/samples/pager.html
+++ /dev/null
@@ -1,23 +0,0 @@
-{% load i18n querystring %}
-
-{% if page_obj.has_previous or page_obj.has_next %}
-
-    <ul class="{% block pagination_class %}pager{% endblock %}">
-
-        {% if page_obj.has_previous %}
-            <li class="previous"><a href="?{% querystring request key='page' value=page_obj.previous_page_number %}">&larr; {% trans "Previous" %}</a></li>
-        {% else %}
-            <li class="previous disabled"><a href="#">&larr; {% trans "Previous" %}</a></li>
-        {% endif %}
-
-        {% block pages %}{% endblock %}
-
-        {% if page_obj.has_next %}
-            <li class="next"><a href="?{% querystring request key='page' value=page_obj.next_page_number %}">{% trans "Next" %} &rarr;</a></li>
-        {% else %}
-            <li class="next disabled"><a href="#">{% trans "Next" %} &rarr;</a></li>
-        {% endif %}
-    </ul>
-
-{% endif %}
-
diff --git a/src/referentielijsten/templates/samples/pagination.html b/src/referentielijsten/templates/samples/pagination.html
deleted file mode 100644
index f9d3bd2..0000000
--- a/src/referentielijsten/templates/samples/pagination.html
+++ /dev/null
@@ -1,12 +0,0 @@
-{% extends "includes/pager.html" %}
-{% load i18n querystring %}
-
-{% block pagination_class %}pagination{% endblock %}
-
-{% block pages %}
-
-    {% for p in paginator.page_range %}
-        <li {% if p == page.number %}class="active"{% endif %}><a href="?{% querystring request key='page' value=p %}">{{ p }}</a></li>
-    {% endfor %}
-
-{% endblock %}
diff --git a/src/referentielijsten/templates/sniplates/form.html b/src/referentielijsten/templates/sniplates/form.html
deleted file mode 100644
index 757fc0f..0000000
--- a/src/referentielijsten/templates/sniplates/form.html
+++ /dev/null
@@ -1,102 +0,0 @@
-{% extends 'sniplates/django.html' %}
-{% load sniplates staticfiles i18n %}
-
-
-{% block _label %}
-{% if label %}
-    <label class="label{% if help_text %} label--tooltip{% endif %}{% if label_classes %} {{ label_classes }}{% endif %}" for="{{ id_for_label }}">
-        {{ label }}
-    </label>
-{% endif %}
-{% endblock %}
-
-
-{% block _errors %}
-{% if errors %}
-    {% for error in errors %}
-        <span class="notification notification--error notification--complete {{ error_position }}" title="{{ error }}">{{ error }}</span>
-    {% endfor %}
-{% endif %}
-{% endblock %}
-
-
-{% block input %}
-{% with input_type=input_type|default:"text" %}
-<input type="{{ input_type }}"
-    name="{{ html_name }}"
-    id="{{ id }}"
-    value="{{ raw_value|default:'' }}"
-    class="input {{ css_classes }} {{ errors|yesno:'input--error,' }}"
-    {{ widget.attrs|flatattrs }}
-    {{ required|yesno:"required," }}
-    {% if autofocus %}autofocus{% endif %}
-    {% if accept %}accept="{{ accept }}"{% endif %}
-    {% if placeholder %}placeholder="{{ placeholder }}"{% endif %}
->
-{% endwith %}
-{% endblock %}
-
-
-{% block TextInput %}
-{% reuse "_label" %}
-{% reuse "input" %}
-
-{% if not no_error %}
-    {% reuse "_errors" %}
-{% endif %}
-{% endblock %}
-
-
-{% block EmailInput %}
-{% reuse "_label" %}
-{% reuse "input" input_type="email" %}
-{% reuse "_errors" %}
-{% endblock %}
-
-
-{% block NumberInput %}
-{% reuse "_label" %}
-{% reuse "input" input_type="number" raw_value=value %}
-{% reuse "_errors" %}
-{% endblock %}
-
-
-{% block URLInput %}
-{% reuse "_label" %}
-{% reuse "input" input_type="url" %}
-{% reuse "_errors" %}
-{% endblock %}
-
-
-{% block PasswordInput %}
-{% reuse "_label" %}
-{% reuse "input" input_type="password" value="" %}
-{% reuse "_errors" %}
-{% endblock %}
-
-
-{% block Textarea %}
-{% reuse "_label" %}
-<textarea name="{{ html_name }}" id="{{ id }}"
-    class="input {{ css_classes }} {{ errors|yesno:'input--error,' }}"
-    {{ required|yesno:"required," }}
-    {% if placeholder %}placeholder="{{ placeholder }}"{% endif %}
-    {{ widget.attrs|flatattrs }}
->{{ raw_value|default:'' }}</textarea>
-{% reuse "_errors" %}
-{% endblock %}
-
-
-{% block RadioButton %}
-<div id="{{ id }}" class="radio-buttons">
-    {% for val, display in choices %}
-        <div class="radio-buttons__container">
-            <input name="{{ html_name }}" class="radio-buttons__input" type="radio" id="{{ id}}_{{ forloop.counter0 }}" value="{{ val }}" {% if val == value|default:"" %}checked{% endif %}>
-            <label class="radio-buttons__label" for="{{ id }}_{{ forloop.counter0 }}">
-                {{ display }}
-            </label>
-        </div>
-    {% endfor %}
-</div>
-{% reuse "_errors" %}
-{% endblock %}
diff --git a/src/referentielijsten/utils/pdf.py b/src/referentielijsten/utils/pdf.py
deleted file mode 100644
index 2b577e3..0000000
--- a/src/referentielijsten/utils/pdf.py
+++ /dev/null
@@ -1,125 +0,0 @@
-"""
-Utilities for PDF rendering from HTML using WeasyPrint.
-
-Note that you need to add https://pypi.org/project/weasyprint/ to your dependencies
-if you want to make use of HTML-to-PDF rendering. This is not included by default as
-it's quite heavy and requires OS-level dependencies.
-
-This module exposes the public function :func:`render_to_pdf` which renders a template
-with a context into a PDF document (bytes output). You can use "external" stylesheets
-in these templates, and they will be resolved through django's staticfiles machinery
-by the custom :class:`UrlFetcher`.
-"""
-
-import logging
-import mimetypes
-from io import BytesIO
-from pathlib import PurePosixPath
-from typing import Tuple
-from urllib.parse import urljoin, urlparse
-
-from django.conf import settings
-from django.contrib.staticfiles import finders
-from django.contrib.staticfiles.storage import staticfiles_storage
-from django.core.files.storage import FileSystemStorage, default_storage
-from django.template.loader import render_to_string
-
-import weasyprint
-
-logger = logging.getLogger(__name__)
-
-__all__ = ["render_to_pdf"]
-
-
-def get_base_url() -> str:
-    """
-    Get the base URL where the project is served.
-
-    You should tweak this after starting the project with a solution fitting
-    your project, as we cannot guess your set-up or where your project is hosted.
-
-    The base URL is required to be able to download/resolve custom fonts and/or any
-    image URLs included in the document to render.
-    """
-    # some hints:
-    # * define a setting `BASE_URL` in your settings matching the canonical domain where
-    #   your project is deployed
-    # * if you only need to serve static assets (=no user-uploaded content), you can use
-    #   a dummy URL like "https://referentielijsten.dev"
-    raise NotImplementedError("You must implement 'get_base_url'.")
-
-
-class UrlFetcher:
-    """
-    URL fetcher that skips the network for /static/* files.
-    """
-
-    def __init__(self):
-        self.static_url = self._get_fully_qualified_url(settings.STATIC_URL)
-        is_static_local_storage = issubclass(
-            staticfiles_storage.__class__, FileSystemStorage
-        )
-
-        self.media_url = self._get_fully_qualified_url(settings.MEDIA_URL)
-        is_media_local_storage = issubclass(
-            default_storage.__class__, FileSystemStorage
-        )
-
-        self.candidates = (
-            (self.static_url, staticfiles_storage, is_static_local_storage),
-            (self.media_url, default_storage, is_media_local_storage),
-        )
-
-    @staticmethod
-    def _get_fully_qualified_url(setting: str):
-        fully_qualified_url = setting
-        if not urlparse(setting).netloc:
-            fully_qualified_url = urljoin(get_base_url(), setting)
-        return urlparse(fully_qualified_url)
-
-    def __call__(self, url: str) -> dict:
-        orig_url = url
-        parsed_url = urlparse(url)
-
-        candidate = self.get_match_candidate(parsed_url)
-        if candidate is not None:
-            base_url, storage = candidate
-            path = PurePosixPath(parsed_url.path).relative_to(base_url.path)
-
-            absolute_path = None
-            if storage.exists(path):
-                absolute_path = storage.path(path)
-            elif settings.DEBUG and storage is staticfiles_storage:
-                # use finders so that it works in dev too, we already check that it's
-                # using filesystem storage earlier
-                absolute_path = finders.find(str(path))
-
-            if absolute_path is None:
-                logger.error("Could not resolve path '%s'", path)
-                return weasyprint.default_url_fetcher(orig_url)
-
-            content_type, encoding = mimetypes.guess_type(absolute_path)
-            result = dict(
-                mime_type=content_type,
-                encoding=encoding,
-                redirected_url=orig_url,
-                filename=path.parts[-1],
-            )
-            with open(absolute_path, "rb") as f:
-                result["file_obj"] = BytesIO(f.read())
-            return result
-        return weasyprint.default_url_fetcher(orig_url)
-
-
-def render_to_pdf(template_name: str, context: dict) -> Tuple[str, bytes]:
-    """
-    Render a (HTML) template to PDF with the given context.
-    """
-    rendered_html = render_to_string(template_name, context=context)
-    html_object = weasyprint.HTML(
-        string=rendered_html,
-        url_fetcher=UrlFetcher(),
-        base_url=get_base_url(),
-    )
-    pdf: bytes = html_object.write_pdf()
-    return rendered_html, pdf
diff --git a/src/referentielijsten/utils/tests/test_celery_beat.py b/src/referentielijsten/utils/tests/test_celery_beat.py
deleted file mode 100644
index a83e04e..0000000
--- a/src/referentielijsten/utils/tests/test_celery_beat.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from unittest import skipIf
-
-from django.conf import settings
-from django.test import SimpleTestCase
-from django.utils.module_loading import import_string
-
-
-class BeatConfigTests(SimpleTestCase):
-    @skipIf(
-        not hasattr(settings, "CELERY_BEAT_SCHEDULE"),
-        "Project does not have celery (beat config)",
-    )
-    def test_task_references_correct(self):
-        """
-        Assert that the task import paths in the Beat config are valid.
-        """
-        for entry in settings.CELERY_BEAT_SCHEDULE.values():
-            task = entry["task"]
-            with self.subTest(task=task):
-                try:
-                    import_string(task)
-                except ImportError:
-                    self.fail(
-                        f"Could not import task '{task}' in settings.CELERY_BEAT_SCHEDULE"
-                    )