diff --git a/contracts/admin.py b/contracts/admin.py
index 3f93aeb673053e8e25d0ce1320fcb287237f0b62..a5474b072572315009a6e7951f313b3fedb9333b 100644
--- a/contracts/admin.py
+++ b/contracts/admin.py
@@ -1,6 +1,8 @@
 from dal_admin_filters import AutocompleteFilter
 from django.contrib import admin
 from django.utils.html import format_html
+from import_export import resources
+from rangefilter.filters import DateRangeFilter
 
 from shared.admin import MarkdownxGuardedModelAdmin
 
@@ -21,6 +23,11 @@ from .models import (
 )
 
 
+class ContractResource(resources.ModelResource):
+    class Meta:
+        model = Contract
+
+
 class IndexHiddenModelAdmin(MarkdownxGuardedModelAdmin):
     def has_module_permission(self, request):
         return False
@@ -31,8 +38,8 @@ class IndexHiddenModelAdmin(MarkdownxGuardedModelAdmin):
 
 class ContractAuthorPlaceholderFilter(AutocompleteFilter):
     title = "Autor"
-    field_name = "author"
-    autocomplete_url = ""
+    field_name = "created_by"
+    autocomplete_url = "users:select2_djhacker_user_autocomplete"
 
 
 # END Autocompletes
@@ -175,10 +182,23 @@ class ContractAdmin(MarkdownxGuardedModelAdmin):
         super().save_model(request, obj, form, change)
 
     list_filter = (
-        ContracteePlaceholderFilter,
-        SigneePlaceholderFilter,
+        "types",
+        "approval_state",
+        "legal_state",
+        "public_state",
+        "paper_form_state",
+        ContractAuthorPlaceholderFilter,
+        "issues",
+        ("all_parties_sign_date", DateRangeFilter),
+        ("valid_start_date", DateRangeFilter),
+        ("valid_end_date", DateRangeFilter),
     )
 
+    list_display = (
+        "name",
+        "approval_state",
+        "public_state",
+    )
 
 # END Contracts
 
@@ -209,6 +229,9 @@ class SigneeAdmin(MarkdownxGuardedModelAdmin):
 
     readonly_fields = ("load_ares_data_button",)
 
+    list_filter = ("entity_type",)
+    list_display = ("name", "entity_type")
+
     inlines = (SigneeRepresentativeInline,)
 
     def load_ares_data_button(self, obj):
diff --git a/contracts/migrations/0010_alter_contractee_address_country_and_more.py b/contracts/migrations/0010_alter_contractee_address_country_and_more.py
new file mode 100644
index 0000000000000000000000000000000000000000..0848e91104082359695d27e41baef63a9b284113
--- /dev/null
+++ b/contracts/migrations/0010_alter_contractee_address_country_and_more.py
@@ -0,0 +1,23 @@
+# Generated by Django 4.1.4 on 2023-03-10 19:16
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('contracts', '0009_alter_contractee_address_country_and_more'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='contractee',
+            name='address_country',
+            field=models.CharField(default='Česká Republika', max_length=256, verbose_name='Země'),
+        ),
+        migrations.AlterField(
+            model_name='signee',
+            name='address_country',
+            field=models.CharField(default='Česká Republika', max_length=256, verbose_name='Země'),
+        ),
+    ]
diff --git a/contracts/models.py b/contracts/models.py
index e780429ffd42ac56862df54b801eff45cebfe128..509ed7daaf5aced4a101b16520c85ce5c074d621 100644
--- a/contracts/models.py
+++ b/contracts/models.py
@@ -98,6 +98,8 @@ class Signee(models.Model):
     )
 
     class Meta:
+        app_label = "contracts"
+
         verbose_name = "Jiná smluvní strana"
         verbose_name_plural = "Ostatní smluvní strany"
 
@@ -145,6 +147,8 @@ class SigneeRepresentative(RepresentativeMixin, models.Model):
     )
 
     class Meta:
+        app_label = "contracts"
+
         verbose_name = "Zástupce"
         verbose_name_plural = "Zástupci"
 
@@ -203,6 +207,8 @@ class Contractee(models.Model):
     )
 
     class Meta:
+        app_label = "contracts"
+
         verbose_name = "Naše smluvní strana"
         verbose_name_plural = "Naše smluvní strany"
 
@@ -244,6 +250,8 @@ class ContracteeRepresentative(RepresentativeMixin, models.Model):
     )
 
     class Meta:
+        app_label = "contracts"
+
         verbose_name = "Zástupce"
         verbose_name_plural = "Zástupci"
 
@@ -255,6 +263,8 @@ class ContractType(NameStrMixin, models.Model):
     )
 
     class Meta:
+        app_label = "contracts"
+
         verbose_name = "Typ smlouvy"
         verbose_name_plural = "Typy smlouvy"
 
@@ -266,6 +276,8 @@ class ContractIssue(NameStrMixin, models.Model):
     )
 
     class Meta:
+        app_label = "contracts"
+
         verbose_name = "Problém se smlouvou"
         verbose_name_plural = "Problémy se smlouvami"
 
@@ -282,11 +294,13 @@ class ContractFilingArea(NameStrMixin, models.Model):
     )
 
     class Meta:
+        app_label = "contracts"
+
         verbose_name = "Spisovna"
         verbose_name_plural = "Spisovny"
 
 
-class Contract(models.Model):
+class Contract(NameStrMixin, models.Model):
     # BEGIN Automatically set fields
 
     created_by = models.ForeignKey(
@@ -482,6 +496,8 @@ class Contract(models.Model):
     )
 
     class Meta:
+        app_label = "contracts"
+
         verbose_name = "Smlouva"
         verbose_name_plural = "Smlouvy"
 
@@ -493,20 +509,6 @@ class Contract(models.Model):
             is_public=True,
         ).all()
 
-    def __str__(self) -> str:
-        result = ""
-        
-        if self.approval_state == Contract.ApprovalStates.YES:
-            result += "SCHVÁLENÁ - "
-        elif self.approval_state == Contract.ApprovalStates.NO:
-            result += "NESCHVÁLENÁ - "
-        else:
-            result += "KE ZPRACOVÁNÍ - "
-
-        result += self.name
-
-        return result
-
 
 class ContractFile(NameStrMixin, models.Model):
     name = models.CharField(
@@ -533,6 +535,8 @@ class ContractFile(NameStrMixin, models.Model):
     )
 
     class Meta:
+        app_label = "contracts"
+
         verbose_name = "Soubor"
         verbose_name_plural = "Soubory"
 
@@ -557,6 +561,8 @@ class ContracteeSignature(models.Model):
     )
 
     class Meta:
+        app_label = "contracts"
+
         verbose_name = "Podpis naší smluvní strany"
         verbose_name_plural = "Podpisy našich smluvních stran"
 
@@ -597,6 +603,8 @@ class SigneeSignature(models.Model):
     )
 
     class Meta:
+        app_label = "contracts"
+
         verbose_name = "Podpis jiné smluvní strany"
         verbose_name_plural = "Podpisy ostatních smluvních stran"
 
@@ -636,5 +644,7 @@ class ContractIntent(NameStrMixin, models.Model):
     )
 
     class Meta:
+        app_label = "contracts"
+
         verbose_name = "Záměr"
         verbose_name_plural = "Záměry"
diff --git a/registry/settings/base.py b/registry/settings/base.py
index c25e824f3e3f343c86b77dc2f7b0c4cb4f2c9b3f..333f1295adbd8915a4b3d015f9eccde2e3dd59f0 100644
--- a/registry/settings/base.py
+++ b/registry/settings/base.py
@@ -48,19 +48,23 @@ INSTALLED_APPS = [
     "dal",
     "dal_select2",
     "dal_admin_filters",
+    "django_admin_index",
+    "ordered_model",
+    "shared",
     "django.contrib.admin",
     "django.contrib.auth",
     "django.contrib.contenttypes",
     "django.contrib.sessions",
     "django.contrib.messages",
     "django.contrib.staticfiles",
+    "import_export",
+    "rangefilter",
     "guardian",
     "markdownx",
     "pirates",
     "webpack_loader",
     "contracts",
     "oidc",
-    "shared",
     "users",
 ]
 
@@ -81,7 +85,9 @@ ROOT_URLCONF = "registry.urls"
 TEMPLATES = [
     {
         "BACKEND": "django.template.backends.django.DjangoTemplates",
-        "DIRS": [],
+        "DIRS": [
+            os.path.join(BASE_DIR, "registry")
+        ],
         "APP_DIRS": True,
         "OPTIONS": {
             "context_processors": [
@@ -179,6 +185,11 @@ WEBPACK_LOADER = {
 }
 
 
+## Media files
+
+MEDIA_URL = "media/"
+
+
 ## Server
 
 USE_X_FORWARDED_HOST = True
@@ -188,6 +199,12 @@ X_FRAME_OPTIONS = "SAMEORIGIN"
 SILENCED_SYSTEM_CHECKS = ["security.W019"]
 
 
+## Admin
+
+ADMIN_INDEX_AUTO_CREATE_APP_GROUP = True
+ADMIN_INDEX_SHOW_REMAINING_APPS = True
+
+
 ## App-specific
 
 DEFAULT_CONTRACTEE_NAME = env.str("DEFAULT_CONTRACTEE_NAME")
diff --git a/registry/templates/admin/base.html b/registry/templates/admin/base.html
new file mode 100644
index 0000000000000000000000000000000000000000..103f27d5a47f2943608c2b206ded2e578beb3297
--- /dev/null
+++ b/registry/templates/admin/base.html
@@ -0,0 +1,10 @@
+{% extends 'admin/base.html' %}
+
+{% block extrastyle %}{{ block.super }}
+<style>
+    :root {
+        --djai-tab-bg: #ff0080;
+        --djai-tab-bg--hover: #a91b60;
+    }
+</style>
+{% endblock %} 
diff --git a/registry/urls.py b/registry/urls.py
index 2a4013ea030f2d6cb57293fdf8f0bea69cdcca38..fbd47f4f0586ae05794842d95ab96b929a8cf413 100644
--- a/registry/urls.py
+++ b/registry/urls.py
@@ -13,13 +13,26 @@ Including another URLconf
     1. Import the include() function: from django.urls import include, path
     2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
 """
+
+from django.conf import settings
 from django.contrib import admin
-from django.urls import include, path
+from django.urls import include, path, re_path
+from django.views.static import serve
 from pirates.urls import urlpatterns as pirates_urlpatterns
 
 urlpatterns = [
     path("", include("contracts.urls")),
+    path("", include("users.urls")),
     path("markdownx/", include("markdownx.urls")),
     path("oidc/", include("oidc.urls")),
     path("admin/", admin.site.urls),
 ] + pirates_urlpatterns
+
+if settings.DEBUG:
+    urlpatterns.append(
+        re_path(
+            r"^media/(?P<path>.*)$",
+            serve,
+            {"document_root": settings.MEDIA_ROOT}
+        ),
+    )
diff --git a/requirements/base.txt b/requirements/base.txt
index f743df87fab2d83d52426933b63df0889d4fdfbb..9fd8bfa52a579ef340992f7d117b5ac379d74d29 100644
--- a/requirements/base.txt
+++ b/requirements/base.txt
@@ -1,8 +1,11 @@
 dal-admin-filters==1.1.0
 django==4.1.4
+django-admin-index==2.0.2
 django-admin-interface==0.24.2
+django-admin-rangefilter==0.9.0
 django-autocomplete-light==3.9.4
 django-database-url==1.0.3
+django-import-export==3.1.0
 djhacker==0.2.3
 psycopg2-binary==2.9.5
 django-webpack-loader==1.8.0
diff --git a/static_src/admin/admin_index_custom.css b/static_src/admin/admin_index_custom.css
new file mode 100644
index 0000000000000000000000000000000000000000..4216cd1ad126fb39036d1687abf0f3fcf4b29577
--- /dev/null
+++ b/static_src/admin/admin_index_custom.css
@@ -0,0 +1,4 @@
+:root {
+    --djai-tab-bg: #ff0080;
+    --djai-tab-bg--hover: #a91b60;
+} 
diff --git a/users/admin.py b/users/admin.py
index 8c38f3f3dad51e4585f3984282c2a4bec5349c1e..d2e7cac9cda39bc9169098b90e87182b9559c76e 100644
--- a/users/admin.py
+++ b/users/admin.py
@@ -1,3 +1,7 @@
 from django.contrib import admin
 
-# Register your models here.
+from shared.admin import MarkdownxGuardedModelAdmin
+
+from .models import User
+
+admin.site.register(User, MarkdownxGuardedModelAdmin)
diff --git a/users/apps.py b/users/apps.py
index 88f7b1798e7f1150a0e4e86781d9533d9573db3d..abeee2f0c63140b6b17c3c95beb9aa8c2cf92a04 100644
--- a/users/apps.py
+++ b/users/apps.py
@@ -4,3 +4,4 @@ from django.apps import AppConfig
 class UsersConfig(AppConfig):
     default_auto_field = "django.db.models.BigAutoField"
     name = "users"
+    verbose_name = "Uživatelé"
diff --git a/users/migrations/0002_alter_user_options.py b/users/migrations/0002_alter_user_options.py
new file mode 100644
index 0000000000000000000000000000000000000000..2de062f1b4382f8323c5e4ed0eac1e32cf4d7442
--- /dev/null
+++ b/users/migrations/0002_alter_user_options.py
@@ -0,0 +1,17 @@
+# Generated by Django 4.1.4 on 2023-03-10 20:07
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('users', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='user',
+            options={},
+        ),
+    ]
diff --git a/users/models.py b/users/models.py
index 11e82baf8f2eae2b3caf8dcbdd10dce9d39caef4..6334f7199c12eed982f8859e6ce109b424be1f9c 100644
--- a/users/models.py
+++ b/users/models.py
@@ -13,3 +13,8 @@ class User(pirates_models.AbstractUser):
             first_name += " "
 
         return f"{first_name}{self.last_name}"
+
+    class Meta:
+        app_label = "users"
+        verbose_name = "Uživatel"
+        verbose_name_plural = "Uživatelé"
diff --git a/users/urls.py b/users/urls.py
new file mode 100644
index 0000000000000000000000000000000000000000..cc5e95051fe7f770a6b77c339789047d50adf9bc
--- /dev/null
+++ b/users/urls.py
@@ -0,0 +1,14 @@
+import dal.autocomplete
+
+from django.urls import path
+
+from . import views, models
+
+app_name = "users"
+urlpatterns = [
+    path(
+        "autocomplete",
+        dal.autocomplete.Select2QuerySetView.as_view(model=models.User),
+        name="select2_djhacker_user_autocomplete",
+    ),
+]