diff --git a/aleksis/apps/resint/migrations/0006_livedocument.py b/aleksis/apps/resint/migrations/0006_livedocument.py
index 0065c61addd0ed16f283c461fb98cdf1585ed989..d7f55e31d14cac2ac795f27d8d8df4827d1b9bc3 100644
--- a/aleksis/apps/resint/migrations/0006_livedocument.py
+++ b/aleksis/apps/resint/migrations/0006_livedocument.py
@@ -1,5 +1,6 @@
-# Generated by Django 3.2.5 on 2021-08-03 18:02
+# Generated by Django 3.2.4 on 2021-08-05 14:20
 
+import aleksis.core.managers
 from django.db import migrations, models
 import django.db.models.deletion
 
@@ -7,6 +8,7 @@ import django.db.models.deletion
 class Migration(migrations.Migration):
 
     dependencies = [
+        ('sites', '0002_alter_domain_unique'),
         ('contenttypes', '0002_remove_content_type_name'),
         ('resint', '0005_fix_permissions'),
     ]
@@ -16,15 +18,20 @@ class Migration(migrations.Migration):
             name='LiveDocument',
             fields=[
                 ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('extended_data', models.JSONField(default=dict, editable=False)),
                 ('slug', models.SlugField(help_text='This will be used for the name of the current PDF file.', verbose_name='Slug')),
                 ('name', models.CharField(max_length=255, verbose_name='Name')),
-                ('last_update', models.DateTimeField(blank=True, null=True, verbose_name='Date and time of the last update', editable=False)),
-                ('current_file', models.FileField(blank=True, null=True, upload_to='chronos/plan_pdfs/', verbose_name='Current file', editable=False)),
+                ('current_file', models.FileField(blank=True, editable=False, null=True, upload_to='live_documents/', verbose_name='Current file')),
+                ('last_update_triggered_manually', models.BooleanField(default=False, editable=False, verbose_name='Was the last update triggered manually?')),
                 ('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_resint.livedocument_set+', to='contenttypes.contenttype')),
+                ('site', models.ForeignKey(default=1, editable=False, on_delete=django.db.models.deletion.CASCADE, to='sites.site')),
             ],
             options={
                 'verbose_name': 'Live document',
                 'verbose_name_plural': 'Live documents',
             },
+            managers=[
+                ('objects', aleksis.core.managers.PolymorphicCurrentSiteManager()),
+            ],
         ),
     ]
diff --git a/aleksis/apps/resint/models.py b/aleksis/apps/resint/models.py
index 1b47450b0d2f5f38f5552d344f5a3aaabf612466..b0c0d5c070a838f974080b92c4c1c87c3c08f182 100644
--- a/aleksis/apps/resint/models.py
+++ b/aleksis/apps/resint/models.py
@@ -7,11 +7,12 @@ from django.db import models
 from django.utils import timezone
 from django.utils.translation import gettext_lazy as _
 
+import reversion
 from calendarweek import CalendarWeek
 from calendarweek.django import i18n_day_name_choices_lazy
-from polymorphic.models import PolymorphicModel
+from reversion.models import Revision, Version
 
-from aleksis.core.mixins import ExtensibleModel
+from aleksis.core.mixins import ExtensibleModel, ExtensiblePolymorphicModel
 
 
 class PosterGroup(ExtensibleModel):
@@ -145,8 +146,8 @@ class Poster(ExtensibleModel):
         return timezone.datetime.combine(day, self.group.publishing_time)
 
 
-class LiveDocument(PolymorphicModel):
-    """Model for periodically/automatically updated PDF files."""
+class LiveDocument(ExtensiblePolymorphicModel):
+    """Model for periodically/automatically updated files."""
 
     slug = models.SlugField(
         verbose_name=_("Slug"),
@@ -154,9 +155,6 @@ class LiveDocument(PolymorphicModel):
     )
     name = models.CharField(max_length=255, verbose_name=_("Name"))
 
-    last_update = models.DateTimeField(
-        blank=True, null=True, verbose_name=_("Date and time of the last update"), editable=False
-    )
     current_file = models.FileField(
         upload_to="live_documents/",
         null=True,
@@ -164,25 +162,51 @@ class LiveDocument(PolymorphicModel):
         verbose_name=_("Current file"),
         editable=False,
     )
+    last_update_triggered_manually = models.BooleanField(
+        default=False, verbose_name=_("Was the last update triggered manually?"), editable=False
+    )
 
-    def update(self, file: Optional[File] = None):
-        """Set a new PDF file as current file."""
-        if file:
-            self.current_file.save("current.pdf", file)
-            self.last_update = timezone.now()
-            self.save()
+    @property
+    def last_version(self) -> Optional[Revision]:
+        """Get django-reversion version of last file update."""
+        versions = Version.objects.get_for_object(self).order_by("revision__date_created")
+        if versions.exists():
+            return versions.last()
+        return None
+
+    @property
+    def last_update(self) -> Optional[datetime]:
+        """Get datetime of last file update."""
+        last_version = self.last_version
+        if last_version:
+            return last_version.revision.date_created
+        return None
 
     def get_current_file(self) -> Optional[File]:
-        """Get current PDF file."""
+        """Get current file."""
         if not self.current_file:
             self.update()
-        return self.current_file.file if self.current_file else None
+        return self.current_file
 
     @property
     def filename(self) -> str:
         """Get the filename without path of the PDF file."""
         return f"{self.slug}.pdf"
 
+    def save(self, *args, **kwargs):
+        with reversion.create_revision():
+            super().save(*args, **kwargs)
+
+    def update(self, triggered_manually: bool = True):
+        """Update the file with a new version.
+
+        Has to be implemented by subclasses.
+        """
+        pass
+
+    def __str__(self) -> str:
+        return self.name
+
     class Meta:
         verbose_name = _("Live document")
         verbose_name_plural = _("Live documents")
diff --git a/aleksis/apps/resint/views.py b/aleksis/apps/resint/views.py
index 28d5ff54b4f0f155349869a42c4e7599c9edafa7..abef233ed69b751e1f236a92aebf5b96658a5a8a 100644
--- a/aleksis/apps/resint/views.py
+++ b/aleksis/apps/resint/views.py
@@ -232,4 +232,4 @@ class LiveDocumentShowView(PermissionRequiredMixin, SingleObjectMixin, View):
         file = live_document.get_current_file()
         if not file:
             raise Http404
-        return FileResponse(live_document.get_current_file(), content_type="application/pdf")
+        return FileResponse(file.file, content_type="application/pdf")