diff --git a/SciPost_v1/settings/base.py b/SciPost_v1/settings/base.py
index 973866cd338b4f1b9d2d272c44ab1e653c78eeea..5c11fc2fe96726a44c6b55c77f2763ae328bb1ab 100644
--- a/SciPost_v1/settings/base.py
+++ b/SciPost_v1/settings/base.py
@@ -99,6 +99,7 @@ INSTALLED_APPS = (
     'submissions',
     'theses',
     'virtualmeetings',
+    'preprints',
     'proceedings',
     'production',
     'partners',
diff --git a/SciPost_v1/urls.py b/SciPost_v1/urls.py
index 2fe82bebd8ad297c4505b5fc1f5794bca5e8035d..6ce1a6e00169f379233be7f11aee5d460db4bbd2 100644
--- a/SciPost_v1/urls.py
+++ b/SciPost_v1/urls.py
@@ -47,6 +47,7 @@ urlpatterns = [
     url(r'^news/', include('news.urls', namespace="news")),
     url(r'^notifications/', include('notifications.urls', namespace="notifications")),
     url(r'^petitions/', include('petitions.urls', namespace="petitions")),
+    url(r'^preprints/', include('preprints.urls', namespace="preprints")),
     url(r'^proceedings/', include('proceedings.urls', namespace="proceedings")),
     url(r'^production/', include('production.urls', namespace="production")),
     url(r'^partners/', include('partners.urls', namespace="partners")),
diff --git a/preprints/admin.py b/preprints/admin.py
new file mode 100644
index 0000000000000000000000000000000000000000..007cfbf4903795f8692ddfca7f7c143f523759a5
--- /dev/null
+++ b/preprints/admin.py
@@ -0,0 +1,10 @@
+__copyright__ = "Copyright 2016-2018, Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+from django.contrib import admin
+
+from .models import Preprint
+
+
+admin.site.register(Preprint)
diff --git a/preprints/apps.py b/preprints/apps.py
new file mode 100644
index 0000000000000000000000000000000000000000..df188c72b5f6bec46cb1e3fa115ee46fc2db46d4
--- /dev/null
+++ b/preprints/apps.py
@@ -0,0 +1,9 @@
+__copyright__ = "Copyright 2016-2018, Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+from django.apps import AppConfig
+
+
+class ProceedingsConfig(AppConfig):
+    name = 'preprints'
diff --git a/preprints/helpers.py b/preprints/helpers.py
new file mode 100644
index 0000000000000000000000000000000000000000..6c6c0577a4b625d4dc69f26c01ce247afc3bbcaa
--- /dev/null
+++ b/preprints/helpers.py
@@ -0,0 +1,28 @@
+__copyright__ = "Copyright 2016-2018, Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+from django.db.models import Max
+from django.utils import timezone
+
+from .models import Preprint
+
+
+def generate_new_scipost_identifier():
+    """Return an identifier for a new SciPost preprint series without version number."""
+    now = timezone.now()
+    existing_identifier = Preprint.objects.filter(
+        created__year=now.year, created__month=now.month).aggregate(
+        identifier=Max('scipost_preprint_identifier'))['identifier']
+    if not existing_identifier:
+        existing_identifier = '1'
+    else:
+        existing_identifier = str(existing_identifier + 1)
+    return '{year}{month}_{identifier}'.format(
+        year=now.year, month=str(now.month).rjust(2, '0'),
+        identifier=existing_identifier.rjust(5, '0'))
+
+
+def format_scipost_identifier(self, identifier, version=1):
+    return 'scipost_{identifier}v{version}'.format(
+        identifier=identifier, version=version)
diff --git a/preprints/migrations/0001_initial.py b/preprints/migrations/0001_initial.py
new file mode 100644
index 0000000000000000000000000000000000000000..25a0fe796052fa5a622790bbc39b72f1a6005b87
--- /dev/null
+++ b/preprints/migrations/0001_initial.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2018-06-10 18:14
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('submissions', '0025_auto_20180520_1430'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Preprint',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('scipost_preprint_identifier', models.PositiveIntegerField(blank=True, null=True)),
+                ('identifier_wo_vn_nr', models.CharField(blank=True, max_length=25)),
+                ('vn_nr', models.PositiveSmallIntegerField(default=1)),
+                ('url', models.URLField()),
+                ('_file', models.FileField(blank=True, max_length=200, upload_to='UPLOADS/PREPRINTS/%Y/%m/')),
+                ('modified', models.DateTimeField(auto_now=True)),
+                ('created', models.DateTimeField(auto_now_add=True)),
+                ('submission', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='submissions.Submission')),
+            ],
+        ),
+    ]
diff --git a/preprints/migrations/0002_auto_20180610_2014.py b/preprints/migrations/0002_auto_20180610_2014.py
new file mode 100644
index 0000000000000000000000000000000000000000..138259df6ce2e5b4667282adbc46d1baf4fb1712
--- /dev/null
+++ b/preprints/migrations/0002_auto_20180610_2014.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2018-06-10 18:14
+from __future__ import unicode_literals
+from datetime import datetime
+
+from django.db import migrations
+
+
+def create_preprint_instances(apps, schema_editor):
+    """Add a Preprint instance for each existing Submission."""
+    Preprint = apps.get_model('preprints', 'Preprint')
+    Submission = apps.get_model('submissions', 'Submission')
+
+    for submission in Submission.objects.all():
+        dt = datetime(
+            year=submission.submission_date.year,
+            month=submission.submission_date.month,
+            day=submission.submission_date.day)
+        Preprint.objects.create(
+            submission=submission,
+            identifier_wo_vn_nr=submission.arxiv_identifier_wo_vn_nr,
+            vn_nr=submission.arxiv_vn_nr,
+            url=submission.arxiv_link,
+            modifier=submission.latest_activity,
+            created=dt)
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('preprints', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.RunPython(create_preprint_instances),
+    ]
diff --git a/preprints/migrations/__init__.py b/preprints/migrations/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/preprints/models.py b/preprints/models.py
new file mode 100644
index 0000000000000000000000000000000000000000..f08ad2e5bbaf08b0488929a2ac622552fd5e2020
--- /dev/null
+++ b/preprints/models.py
@@ -0,0 +1,44 @@
+__copyright__ = "Copyright 2016-2018, Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+from django.core.urlresolvers import reverse
+from django.db import models
+from django.http import Http404
+
+
+class Preprint(models.Model):
+    """A link with ArXiv or standalone/SciPost-hosted preprint.
+
+    If the instance is a scipost preprint, the `_file` and `scipost_preprint_identifier` fields
+    should be filled. Else, these fields should be left blank.
+    """
+
+    submission = models.OneToOneField('submissions.Submission')
+
+    # (ArXiv) identifiers with/without version number
+    # identifier_w_vn_nr = models.CharField(max_length=25, blank=True)
+    scipost_preprint_identifier = models.PositiveIntegerField(null=True, blank=True)
+    identifier_wo_vn_nr = models.CharField(max_length=25, blank=True)
+    vn_nr = models.PositiveSmallIntegerField(default=1)
+    url = models.URLField()
+
+    _file = models.FileField(upload_to='UPLOADS/PREPRINTS/%Y/%m/', max_length=200, blank=True)
+
+    # Dates
+    modified = models.DateTimeField(auto_now=True)
+    created = models.DateTimeField(auto_now_add=True)
+
+    def __str__(self):
+        return 'Preprint {}'.format(self.identifier_w_vn_nr)
+
+    def get_absolute_url(self):
+        if self.url:
+            return self.url
+        if self._file:
+            return reverse('preprints:pdf', self.identifier_w_vn_nr)
+        raise Http404
+
+    @property
+    def identifier_w_vn_nr(self):
+        return '{}v{}'.format(self.identifier_wo_vn_nr, self.vn_nr)
diff --git a/preprints/tests.py b/preprints/tests.py
new file mode 100644
index 0000000000000000000000000000000000000000..9135c42ab26e15b71fd25dc25d9f92bcec7e676b
--- /dev/null
+++ b/preprints/tests.py
@@ -0,0 +1,7 @@
+__copyright__ = "Copyright 2016-2018, Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/preprints/urls.py b/preprints/urls.py
new file mode 100644
index 0000000000000000000000000000000000000000..6f5dc5eecd2a3cf5e60abaf2cec74b5ab0eaa42a
--- /dev/null
+++ b/preprints/urls.py
@@ -0,0 +1,12 @@
+__copyright__ = "Copyright 2016-2018, Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+from django.conf.urls import url
+
+from . import views
+
+
+urlpatterns = [
+    url(r'^$', views.preprint_pdf, name='pdf'),
+]
diff --git a/preprints/views.py b/preprints/views.py
new file mode 100644
index 0000000000000000000000000000000000000000..67222f676d20dd5ebaad36a05cd7dd16d852c451
--- /dev/null
+++ b/preprints/views.py
@@ -0,0 +1,18 @@
+__copyright__ = "Copyright 2016-2018, Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+from django.http import HttpResponse
+from django.shortcuts import get_object_or_404
+
+from .models import Preprint
+
+
+def preprint_pdf(request, identifier_w_vn_nr):
+    """Download the attachment of a Report if available."""
+    preprint = get_object_or_404(Preprint, identifier_w_vn_nr=identifier_w_vn_nr, _file__isnull=False)
+
+    response = HttpResponse(preprint._file.read(), content_type='application/pdf')
+    filename = '{}_preprint.pdf'.format(preprint.identifier_w_vn_nr)
+    response['Content-Disposition'] = ('filename=' + filename)
+    return response