diff --git a/Dockerfile b/Dockerfile
index 6985c0dd97f345f7008c931855866033f711fdbb..c61507638a5f483b4e35e7ec52d0d6b733337d28 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -43,6 +43,8 @@ RUN DATABASE_URL=postgres://x/x \
     DEFAULT_CONTRACTEE_DISTRICT=x \
     DEFAULT_CONTRACTEE_ICO_NUMBER=x \
     DEFAULT_STAFF_GROUPS=x \
+    NASTENKA_API_URL=x \
+    NASTENKA_API_TOKEN=x \
     python manage.py collectstatic --noinput --settings=registry.settings.production
 
 RUN bash -c "adduser --disabled-login --quiet --gecos app app &&  \
diff --git a/contracts/admin.py b/contracts/admin.py
index e2bb97cae131f3988964e04399cb87660127a4bb..b6080662ca94e9486ea19da965061c3a53ba0f9c 100644
--- a/contracts/admin.py
+++ b/contracts/admin.py
@@ -1,7 +1,11 @@
 import copy
+import json
+import logging
 import typing
 
+import requests
 from admin_auto_filters.filters import AutocompleteFilterFactory
+from django.conf import settings
 from django.contrib import admin
 from django.contrib.auth.models import Permission
 from django.db import models
@@ -33,6 +37,8 @@ from .models import (
     SigneeSignatureRepresentative,
 )
 
+logger = logging.getLogger()
+
 
 class IndexHiddenModelAdmin(MarkdownxGuardedModelAdmin):
     def has_module_permission(self, request):
@@ -314,6 +320,8 @@ class ContractAdmin(
         return queryset
 
     def save_model(self, request, obj, form, change):
+        is_new = obj.created_by is None
+
         # Need to generate primary keys first
         parent_save_response = super().save_model(request, obj, form, change)
 
@@ -333,6 +341,40 @@ class ContractAdmin(
 
             obj.valid_start_date = last_signature_date
 
+        from users.models import User
+
+        if is_new:
+            try:
+                sso_ids = []
+
+                for user in User.objects.filter(is_staff=True).all():
+                    if user.is_superuser or user.has_perm("contracts.approve"):
+                        sso_ids.append(user.sso_id)
+
+                requests.post(
+                    settings.NASTENKA_API_URL,
+                    data=json.dumps(
+                        {
+                            "name": f"Nová smlouva ke schválení - {obj.name}",
+                            "description": (
+                                obj.summary
+                                if obj.summary is not None
+                                else "Bez popisu."
+                            ),
+                            "contract_id": obj.id,
+                            "sso_ids": sso_ids,
+                        }
+                    ),
+                    headers={
+                        "Authorization": f"Token {settings.NASTENKA_API_TOKEN}",
+                        "Content-Type": "application/json",
+                    },
+                )
+            except Exception as exception:
+                logger.error(
+                    "Failed to synchronizace Nástěnka notices: %s", str(exception)
+                )
+
         return parent_save_response
 
     def has_change_permission(self, request, obj=None):
diff --git a/contracts/migrations/0062_contract_paper_form_person_responsible.py b/contracts/migrations/0062_contract_paper_form_person_responsible.py
index c73e9cc47cea36375525bec36e908df843f4ed65..1e6d8fea7d684cc890af012a72aee2cc031fb490 100644
--- a/contracts/migrations/0062_contract_paper_form_person_responsible.py
+++ b/contracts/migrations/0062_contract_paper_form_person_responsible.py
@@ -4,15 +4,19 @@ from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
-        ('contracts', '0061_alter_contract_id_number'),
+        ("contracts", "0061_alter_contract_id_number"),
     ]
 
     operations = [
         migrations.AddField(
-            model_name='contract',
-            name='paper_form_person_responsible',
-            field=models.CharField(blank=True, max_length=256, null=True, verbose_name='Osoba zodpovědná za doručení'),
+            model_name="contract",
+            name="paper_form_person_responsible",
+            field=models.CharField(
+                blank=True,
+                max_length=256,
+                null=True,
+                verbose_name="Osoba zodpovědná za doručení",
+            ),
         ),
     ]
diff --git a/contracts/models.py b/contracts/models.py
index 6e4a7a5bb4cfb2050d709be4e6eada49fef2c843..c948ca56e8065b48a4b6dd3ee1e21c28904ceee5 100644
--- a/contracts/models.py
+++ b/contracts/models.py
@@ -747,10 +747,11 @@ class Contract(NameStrMixin, models.Model):
             )
 
         if (
-            self.paper_form_state not in (
+            self.paper_form_state
+            not in (
                 self.PaperFormStates.STORED,
                 self.PaperFormStates.SHREDDED,
-                self.PaperFormStates.LOST
+                self.PaperFormStates.LOST,
             )
             and not self.paper_form_person_responsible
         ):
diff --git a/contracts/templates/contracts/includes/contract_list.html b/contracts/templates/contracts/includes/contract_list.html
index ab5f20ea4c1cdaea74c08104f647b668aa6e599d..0ecc7ce22aea7a4c278d66afecdfcf90a2eb5804 100644
--- a/contracts/templates/contracts/includes/contract_list.html
+++ b/contracts/templates/contracts/includes/contract_list.html
@@ -1,72 +1,4 @@
-<div class="hidden md:block">
-    <table class="table table-auto w-full table--striped table--bordered">
-        <thead>
-            <tr>
-                <td class="font-bold">Název</td>
-                <td>Typy</td>
-                <td>Platná</td>
-                <td class="whitespace-nowrap">Účinná od</td>
-                <td class="whitespace-nowrap">Účinná do</td>
-                <td class="whitespace-nowrap">Podepsána s</td>
-            </tr>
-        </thead>
-        <tbody>
-            {% for contract in page %}
-                <tr>
-                    <td{% if not contract.is_public %} class="!bg-red-100"{% endif %}>
-                        {% if not contract.is_public %}
-                            {% include "contracts/includes/private_info_icon.html" %}
-                        {% endif %}
-                        <a
-                            class="underline"
-                            href="{% url "contracts:view_contract" contract.id %}"
-                        >{{ contract.name }}</a>
-                    </td>
-                    <td{% if not contract.is_public %} class="!bg-red-100"{% endif %}>
-                        <ul class="flex flex-wrap gap-1.5">
-                            {% for type in contract.types.all %}
-                                <li class="flex">
-                                    {% include "contracts/includes/tag.html" with url=type.url icon="ico--folder" content=type.name public=contract.is_public %}
-                                </li>
-                            {% endfor %}
-                        </ul>
-                    </td>
-                    <td{% if not contract.is_public %} class="!bg-red-100"{% endif %}>
-                        <i
-                            class="{% if contract.is_valid %}ico--checkmark{% else %}ico--cross{% endif %}"
-                            aria-label="{% if contract.is_public %}Ano{% else %}Ne{% endif %}"
-                        ></i>
-                    </td>
-                    <td class="whitespace-nowrap{% if not contract.is_public %} !bg-red-100{% endif %}">
-                        {{ contract.valid_start_date }}
-                    </td>
-                    <td class="whitespace-nowrap{% if not contract.is_public %} !bg-red-100{% endif %}">
-                        {% if contract.valid_end_date %}
-                            {{ contract.valid_end_date }}
-                        {% else %}
-                            <span class="text-grey-200">Neurčité</span>
-                        {% endif %}
-                    </td>
-                    <td{% if not contract.is_public %} class="!bg-red-100"{% endif %}>
-                        <ul class="flex flex-wrap gap-1.5">
-                            {% for signature in contract.signee_signatures.all %}
-                                <li class="flex">
-                                    {% if signature.signee.entity_type == signature.signee.EntityTypes.LEGAL_ENTITY or signature.signee.entity_type == signature.signee.EntityTypes.OTHER %}
-                                        {% include "contracts/includes/tag.html" with url=signature.signee.url icon="ico--office" content=signature.signee.name public=contract.is_public %}
-                                    {% else %}
-                                        {% include "contracts/includes/tag.html" with url=signature.signee.url icon="ico--user" content=signature.signee.name public=contract.is_public %}
-                                    {% endif %}
-                                </li>
-                            {% endfor %}
-                        </ul>
-                    </td>
-                </tr>
-            {% endfor %}
-        </tbody>
-    </table>
-</div>
-
-<ul class="flex-col gap-4 flex md:hidden">
+<ul class="flex-col gap-4 flex">
     {% for contract in page %}
         <li class="card elevation-10{% if not contract.is_public %} bg-red-100{% endif %}">
             <div class="card__body p-5">
@@ -96,7 +28,11 @@
                             <tr>
                                 <td class="pt-1.5">Účinná od:</td>
                                 <td class="pt-1.5">
-                                    {{ contract.valid_start_date }}
+                                    {% if contract.valid_start_date %}
+                                        {{ contract.valid_start_date }}
+                                    {% else %}
+                                        <span class="text-grey-200">Neurčité</span>
+                                    {% endif %}
                                 </td>
                             </tr>
                             <tr>
diff --git a/env.example b/env.example
index 6953a74f1702e98fefd374c9e36d12aab239740d..564842df14cd9adec8176efda99a39b4e58a7a13 100644
--- a/env.example
+++ b/env.example
@@ -20,3 +20,6 @@ DEFAULT_CONTRACTEE_DISTRICT="Praha 2"
 DEFAULT_CONTRACTEE_ICO_NUMBER="71339698"
 
 DEFAULT_STAFF_GROUPS="sso_cen:f,sso_cen:neverejni,sso_cen:smlouvy_ao,sso_cen:smlouvy_po,sso_cen:registr_smluv"
+
+NASTENKA_API_URL=http://localhost:8009/contracts/api/notices
+NASTENKA_API_TOKEN=cirno
diff --git a/oidc/auth.py b/oidc/auth.py
index 07cea60a7ee8595ccd7f4ee2902823da600fde29..eb5f1b9a1fa6e47918a864e95f3f87ac2da64471 100644
--- a/oidc/auth.py
+++ b/oidc/auth.py
@@ -53,6 +53,7 @@ class RegistryOIDCAuthenticationBackend(PiratesOIDCAuthenticationBackend):
             access_token, options={"verify_signature": False}
         )
 
+        user.preferred_username = decoded_access_token["preferred_username"]
         user_groups = user.groups.all()
 
         self._remove_old_user_groups(
diff --git a/registry/settings/base.py b/registry/settings/base.py
index 4a468c34cdcf4807397d4929536cc5347e76cd32..a21c828a30449877496e93a9fb213ca01aafed4a 100644
--- a/registry/settings/base.py
+++ b/registry/settings/base.py
@@ -244,6 +244,9 @@ if SENTRY_DSN != "":
 
 ## App-specific
 
+NASTENKA_API_URL = env.str("NASTENKA_API_URL")
+NASTENKA_API_TOKEN = env.str("NASTENKA_API_TOKEN")
+
 DEFAULT_CONTRACTEE_NAME = env.str("DEFAULT_CONTRACTEE_NAME")
 DEFAULT_CONTRACTEE_STREET = env.str("DEFAULT_CONTRACTEE_STREET")
 DEFAULT_CONTRACTEE_ZIP = env.str("DEFAULT_CONTRACTEE_ZIP")
diff --git a/requirements/base.txt b/requirements/base.txt
index e4fe2396bd4a6f5a08f1182a3859258f20f97548..3a13eb48f3660711f4672cfcd4b6e3a44d3de508 100644
--- a/requirements/base.txt
+++ b/requirements/base.txt
@@ -21,3 +21,4 @@ Markdown==3.4.3
 postal==1.1.10
 PyJWT==2.6.0
 PyYAML==6.0
+requests==2.31.0
diff --git a/users/migrations/0004_user_preferred_username_alter_user_sso_id.py b/users/migrations/0004_user_preferred_username_alter_user_sso_id.py
new file mode 100644
index 0000000000000000000000000000000000000000..ffdac3cd719afb65d20e04db8dcef467ea8038a1
--- /dev/null
+++ b/users/migrations/0004_user_preferred_username_alter_user_sso_id.py
@@ -0,0 +1,27 @@
+# Generated by Django 4.1.4 on 2023-06-15 05:52
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("users", "0003_alter_user_is_staff_based_on_group"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="user",
+            name="preferred_username",
+            field=models.CharField(
+                blank=True,
+                max_length=64,
+                null=True,
+                verbose_name="Username v Chobotnici",
+            ),
+        ),
+        migrations.AlterField(
+            model_name="user",
+            name="sso_id",
+            field=models.CharField(max_length=128, verbose_name="SSO ID"),
+        ),
+    ]
diff --git a/users/models.py b/users/models.py
index 83f21bfc393d3c21aa0790ff0854f06b246fa5e4..ab09f228f296456be463480262c1e102c048a9f6 100644
--- a/users/models.py
+++ b/users/models.py
@@ -1,3 +1,5 @@
+import uuid
+
 from django.conf import settings
 from django.contrib.auth.models import Group as AuthGroup
 from django.contrib.auth.models import Permission
@@ -18,6 +20,18 @@ class Group:
 
 
 class User(pirates_models.AbstractUser):
+    preferred_username = models.CharField(
+        max_length=64,
+        verbose_name="Username v Chobotnici",
+        blank=True,
+        null=True,
+    )
+
+    sso_id = models.CharField(
+        "SSO ID",
+        max_length=128,
+    )
+
     is_staff_based_on_group = models.BooleanField(
         default=True,
         verbose_name="Administrační přístup dle členství ve skupině",
@@ -28,6 +42,8 @@ class User(pirates_models.AbstractUser):
         ),
     )
 
+    USERNAME_FIELD = "preferred_username"
+
     @property
     def can_approve_contracts(self) -> bool:
         return self.has_perm("contracts.approve")