diff --git a/Dockerfile b/Dockerfile
index 554f7fe..9a0da78 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -6,9 +6,12 @@ ENV SHELL /bin/bash
 # ------------------------------------------
 # install necessary packages via apt-get:
 # ------------------------------------------
-# RUN apt-get update && \
-# 	apt-get install -y --no-install-recommends \
-# 	libsaxonhe-java
+RUN apt-get update && \
+	apt-get install -y --no-install-recommends \
+	libsasl2-dev python-dev libldap2-dev libssl-dev
+
+# this is supposed to save memory:
+RUN rm -rf /var/lib/apt/lists/*
 
 # ------------------------------------------
 # install python dependencies:
diff --git a/requirements.txt b/requirements.txt
index 589c526..23737bc 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,42 @@
-Django==2.2
-psycopg2-binary
+Django==2.1.11
+psycopg2-binary == 2.7.7
+dj-database-url==0.5.0
+django-auth-ldap==2.0.0
+django-classy-tags==0.9.0
+django-cms==3.6.0
+django-filer==1.5.0
+django-formtools==2.1
+django-js-asset==1.2.2
+django-mptt==0.10.0
+django-polymorphic==2.0.3
+django-sekizai==1.0.0
+django-treebeard==4.3
+djangocms-admin-style==1.4.0
+djangocms-attributes-field==1.1.0
+djangocms-column==1.9.0
+djangocms-file==2.3.0
+djangocms-installer==1.1.1
+djangocms-link==2.5.0
+djangocms-picture==2.1.3
+djangocms-snippet==2.1.0
+djangocms-style==2.2.0
+djangocms-text-ckeditor==3.7.0
+djangocms-video==2.1.1
+easy-thumbnails==2.6
+html5lib==1.0.1
+lxml==4.4.1
+Pillow==6.1.0
+pyasn1==0.4.6
+pyasn1-modules==0.2.6
+python-ldap==3.2.0
+pytz==2019.2
+six==1.12.0
+sqlparse==0.3.0
+tzlocal==2.0.0
+Unidecode==1.0.23
+webencodings==0.5.1
+git+git://github.molgen.mpg.de/EditionOpenAccess/django-eoaauthors
+git+git://github.molgen.mpg.de/EditionOpenAccess/django-eoaforthcoming
+git+git://github.molgen.mpg.de/EditionOpenAccess/django-eoapublications
+git+git://github.molgen.mpg.de/EditionOpenAccess/django-eoaseries
+git+git://github.molgen.mpg.de/EditionOpenAccess/django-opds
diff --git a/src/cms_plugins.py b/src/cms_plugins.py
new file mode 100644
index 0000000..867d4a9
--- /dev/null
+++ b/src/cms_plugins.py
@@ -0,0 +1,10 @@
+from cms.plugin_base import CMSPluginBase
+from cms.plugin_pool import plugin_pool
+from cms.models.pluginmodel import CMSPlugin
+from django.utils.translation import ugettext_lazy as _
+
+@plugin_pool.register_plugin
+class EOASeries(CMSPluginBase):
+    model = CMSPlugin
+    render_template = "eoaseries.html"
+    cache = False
diff --git a/src/eoa/cms_apps.py b/src/eoa/cms_apps.py
new file mode 100644
index 0000000..80032bd
--- /dev/null
+++ b/src/eoa/cms_apps.py
@@ -0,0 +1,18 @@
+from cms.app_base import CMSApp
+from cms.apphook_pool import apphook_pool
+
+@apphook_pool.register
+class EOASeriesApphook(CMSApp):
+    app_name = "eoaseries"  # must match the application namespace
+    name = "EOA Series Apphook"
+
+    def get_urls(self, page=None, language=None, **kwargs):
+        return ["eoaseries.urls"]
+
+@apphook_pool.register
+class EOAAuthorsApphook(CMSApp):
+    app_name = "eoaauthors"  # must match the application namespace
+    name = "EOA Authors Apphook"
+
+    def get_urls(self, page=None, language=None, **kwargs):
+        return ["eoaauthors.urls"]
diff --git a/src/eoa/migrations/__init__.py b/src/eoa/migrations/__init__.py
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/src/eoa/migrations/__init__.py
@@ -0,0 +1 @@
+
diff --git a/src/eoa/settings.py b/src/eoa/settings.py
index b551fcc..7e8ad4b 100644
--- a/src/eoa/settings.py
+++ b/src/eoa/settings.py
@@ -11,9 +11,16 @@
 """
 
 import os
+from pathlib import Path
+import ldap
+from django_auth_ldap.config import LDAPSearch, PosixGroupType
+
+gettext = lambda s: s
 
 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
-BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+BASE_DIR = Path(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+RES_DIR = Path(os.environ['RES_DIR'])
 
 
 # Quick-start development settings - unsuitable for production
@@ -31,22 +38,53 @@
 # Application definition
 
 INSTALLED_APPS = [
-    'django.contrib.admin',
+    'djangocms_admin_style',
     'django.contrib.auth',
     'django.contrib.contenttypes',
     'django.contrib.sessions',
-    'django.contrib.messages',
+    'django.contrib.admin',
+    'django.contrib.sites',
+    'django.contrib.sitemaps',
     'django.contrib.staticfiles',
+    'django.contrib.messages',
+    'cms',
+    'menus',
+    'sekizai',
+    'treebeard',
+    'djangocms_text_ckeditor',
+    'filer',
+    'easy_thumbnails',
+    'djangocms_column',
+    'djangocms_file',
+    'djangocms_link',
+    'djangocms_picture',
+    'djangocms_style',
+    'djangocms_snippet',
+    'djangocms_video',
+
+
+    'eoa',
+    'eoapublications',
+    'eoaforthcoming',
+    'eoaseries',
+    'eoaauthors',
+    'opds',
 ]
 
 MIDDLEWARE = [
-    'django.middleware.security.SecurityMiddleware',
+    'cms.middleware.utils.ApphookReloadMiddleware',
     'django.contrib.sessions.middleware.SessionMiddleware',
-    'django.middleware.common.CommonMiddleware',
     'django.middleware.csrf.CsrfViewMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware',
+    'django.contrib.sites.middleware.CurrentSiteMiddleware',
+    'django.middleware.locale.LocaleMiddleware',
+    'django.middleware.common.CommonMiddleware',
     'django.middleware.clickjacking.XFrameOptionsMiddleware',
+    'cms.middleware.user.CurrentUserMiddleware',
+    'cms.middleware.page.CurrentPageMiddleware',
+    'cms.middleware.toolbar.ToolbarMiddleware',
+    'cms.middleware.language.LanguageCookieMiddleware'
 ]
 
 ROOT_URLCONF = 'eoa.urls'
@@ -54,14 +92,25 @@
 TEMPLATES = [
     {
         'BACKEND': 'django.template.backends.django.DjangoTemplates',
-        'DIRS': [],
-        'APP_DIRS': True,
+        'DIRS': [os.path.join(BASE_DIR, 'eoa', 'templates'),],
+        # 'APP_DIRS': True,
         'OPTIONS': {
             'context_processors': [
-                'django.template.context_processors.debug',
-                'django.template.context_processors.request',
                 'django.contrib.auth.context_processors.auth',
                 'django.contrib.messages.context_processors.messages',
+                'django.template.context_processors.i18n',
+                'django.template.context_processors.debug',
+                'django.template.context_processors.request',
+                'django.template.context_processors.media',
+                'django.template.context_processors.csrf',
+                'django.template.context_processors.tz',
+                'sekizai.context_processors.sekizai',
+                'django.template.context_processors.static',
+                'cms.context_processors.cms_settings'
+            ],
+            'loaders': [
+                'django.template.loaders.filesystem.Loader',
+                'django.template.loaders.app_directories.Loader'
             ],
         },
     },
@@ -75,8 +124,11 @@
 
 DATABASES = {
     'default': {
-        'ENGINE': 'django.db.backends.sqlite3',
-        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
+        'ENGINE': 'django.db.backends.postgresql',
+        'NAME': 'postgres',
+        'USER': 'postgres',
+        'HOST': 'db',
+        'PORT': '5432',
     }
 }
 
@@ -99,13 +151,37 @@
     },
 ]
 
+AUTHENTICATION_BACKENDS = (
+    'django_auth_ldap.backend.LDAPBackend',
+    'django.contrib.auth.backends.ModelBackend',
+)
+
+AUTH_LDAP_SERVER_URI = "ldap://mpiwg-ldap.mpiwg-berlin.mpg.de:7389"
+AUTH_LDAP_BIND_DN = ""
+AUTH_LDAP_BIND_PASSWORD = ""
+AUTH_LDAP_USER_SEARCH = LDAPSearch("cn=users,dc=mpiwg-berlin,dc=mpg,dc=de",
+                                   ldap.SCOPE_SUBTREE, "(uid=%(user)s)")
+AUTH_LDAP_USER_ATTR_MAP = {"first_name": "givenName", "last_name": "sn"}
+AUTH_LDAP_PROFILE_ATTR_MAP = {"home_directory": "homeDirectory"}
+AUTH_LDAP_GROUP_SEARCH = LDAPSearch("cn=groups,dc=mpiwg-berlin,dc=mpg,dc=de",
+                                    ldap.SCOPE_SUBTREE, "(objectClass=posixGroup)")
+AUTH_LDAP_GROUP_TYPE = PosixGroupType()
+AUTH_LDAP_MIRROR_GROUPS = True
+
+# Use LDAP group membership to calculate group permissions.
+AUTH_LDAP_FIND_GROUP_PERMS = True
+AUTH_LDAP_USER_FLAGS_BY_GROUP = {
+    "is_active": "cn=mpiwg,cn=groups,dc=mpiwg-berlin,dc=mpg,dc=de",
+    "is_staff": "cn=mpiwg,cn=groups,dc=mpiwg-berlin,dc=mpg,dc=de"
+}
+
 
 # Internationalization
 # https://docs.djangoproject.com/en/2.2/topics/i18n/
 
-LANGUAGE_CODE = 'en-us'
+LANGUAGE_CODE = 'en'
 
-TIME_ZONE = 'UTC'
+TIME_ZONE = 'Europe/Berlin'
 
 USE_I18N = True
 
@@ -114,7 +190,59 @@
 USE_TZ = True
 
 
+LANGUAGES = (
+    ## Customize this
+    ('en', gettext('en')),
+)
+
+## CMS config:
+CMS_LANGUAGES = {
+    ## Customize this
+    1: [
+        {
+            'code': 'en',
+            'name': gettext('en'),
+            'redirect_on_fallback': True,
+            'public': True,
+            'hide_untranslated': False,
+        },
+    ],
+    'default': {
+        'redirect_on_fallback': True,
+        'public': True,
+        'hide_untranslated': False,
+    },
+}
+
+CMS_TEMPLATES = (
+    ## Customize this
+    ('fullwidth.html', 'Fullwidth'),
+)
+
+CMS_PERMISSION = True
+
+CMS_PLACEHOLDER_CONF = {}
+
 # Static files (CSS, JavaScript, Images)
 # https://docs.djangoproject.com/en/2.2/howto/static-files/
 
 STATIC_URL = '/static/'
+# where all static files are collected by 'python manage.py collectstatic'
+STATIC_ROOT = RES_DIR / 'all_static_files'
+MEDIA_URL = '/media/'
+MEDIA_ROOT = RES_DIR / 'all_media_files'
+
+STATICFILES_DIRS = [
+    RES_DIR / "static",
+]
+SITE_ID = 1
+
+MIGRATION_MODULES = {
+}
+
+THUMBNAIL_PROCESSORS = (
+    'easy_thumbnails.processors.colorspace',
+    'easy_thumbnails.processors.autocrop',
+    'filer.thumbnail_processors.scale_and_crop_with_subject_location',
+    'easy_thumbnails.processors.filters'
+)
diff --git a/src/eoa/templates/base.html b/src/eoa/templates/base.html
new file mode 100644
index 0000000..558110d
--- /dev/null
+++ b/src/eoa/templates/base.html
@@ -0,0 +1,79 @@
+{% load cms_tags menu_tags sekizai_tags staticfiles %}
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8"/>
+    <title>{% block title %}Edition Open Access{% endblock title %}</title>
+    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1"/>
+    {% block metatags %}{% endblock metatags %}
+    {% block hyperimage %}{% endblock hyperimage %}
+    <link rel="shortcut icon" href="{% static 'assets/images/favicon.png' %}"/>
+    <link rel="apple-touch-icon" href="{% static 'assets/images/favicon-apple.png' %}"/>
+    <link href="{% static '852a3afcc3d6f07ad520.app.css' %}" rel="stylesheet"/>
+    {% render_block "css" %}
+  </head>
+  <body>
+    {% cms_toolbar %}
+    <div class="page">
+      <div class="content">
+        <div class="mobile-header__background"></div>
+        <header class="header">
+          <div class="header__content">
+            <div class="blocklogo container">
+              <div class="blocklogo__logo">
+                <a href="{% page_url 'intropage' %}">
+                  <img class="blocklogo__img" src="{% static 'assets/images/mprl_logo_281x165.png' %}" alt="logo" data-object-fit="cover"/>
+                </a>
+              </div>
+            </div>
+            <nav class="nav">
+              <a class="nav-toggle" href="#">
+                <span class="nav-toggle__item"></span>
+                <span class="nav-toggle__item"></span>
+                <span class="nav-toggle__item"></span>
+              </a>
+              <div class="nav__wrapper">
+                <div class="container">
+                  <ul class="nav__menu">
+                    <!-- <li class="nav__item"> -->
+                      {% show_menu 0 100 100 100 %}
+                    <li class="nav__item nav-search" id="nav-search">
+                      <form class="nav-search-form">
+                        <input class="nav-search__input" placeholder="Search" type="search" value="" name="search" id="search"/>
+                        <input class="nav-search__submit" type="submit" value=""/>
+                      </form>
+                    </li>
+                    <li class="nav__item nav-footer">
+                      <a class="nav__link nav-footer__link" href="{% page_url 'contact' %}">Contact</a><a class="nav__link nav-footer__link" href="{% page_url 'imprint' %}">Imprint</a>
+                    </li>
+                  </ul>
+                </div>
+              </div>
+            </nav>
+            <nav class="breadcrumbs container">
+              <ul class="breadcrumbs__items">
+                {% block breadcrumb %}
+                {% show_breadcrumb %}
+                {% endblock %}
+              </ul>
+            </nav>
+          </div>
+        </header>
+        <!-- <main class="main"> <div class="container"> <div class="main-content"> -->
+              {% block content %}{% endblock content %}
+        <!-- </div> </div> </main> -->
+      </div>
+      <footer class="footer">
+        <div class="footer__content">
+          <div class="footer-menu"><a href="{% page_url 'contact' %}">Contact</a><a href="{% page_url 'imprint' %}">Imprint</a><a class="share" href="#">Share<span>this Page</span></a></div>
+          <div class="footer-logo"><a href="https://mpiwg-berlin.mpg.de/">
+              <h2>Max Planck Institute for the History of Science</h2></a></div>
+        </div>
+      </footer>
+    </div>
+    {% block hyperimagebottom %}{% endblock hyperimagebottom %}
+    <script type="text/javascript" src="{% static '852a3afcc3d6f07ad520.app.js' %}"></script>
+    {% render_block "js" %}
+  </body>
+</html>
diff --git a/src/eoa/templates/fullwidth.html b/src/eoa/templates/fullwidth.html
new file mode 100644
index 0000000..e4c4708
--- /dev/null
+++ b/src/eoa/templates/fullwidth.html
@@ -0,0 +1,14 @@
+{% extends "base.html" %}
+{% load cms_tags %}
+
+{% block title %}{% page_attribute "page_title" %}{% endblock title %}
+
+{% block content %}
+<main class="main">
+  <div class="container">
+    <div class="main-content">
+      {% placeholder "content" %}
+    </div>
+  </div>
+</main>
+{% endblock content %}
diff --git a/src/eoa/templates/menu/breadcrumb.html b/src/eoa/templates/menu/breadcrumb.html
new file mode 100644
index 0000000..d354e78
--- /dev/null
+++ b/src/eoa/templates/menu/breadcrumb.html
@@ -0,0 +1,9 @@
+{% for ance in ancestors %}
+<li class="breadcrumbs__item">
+  {% if not forloop.last %}
+  <a class="breadcrumbs__link" href="{{ ance.get_absolute_url }}">{{ ance.get_menu_title }}</a>
+  {% else %}
+  <span class="breadcrumbs__link-current">{{ ance.get_menu_title }}</span>
+  {% endif %}
+</li>
+{% endfor %}
diff --git a/src/eoa/templates/menu/menu.html b/src/eoa/templates/menu/menu.html
new file mode 100644
index 0000000..93b85fa
--- /dev/null
+++ b/src/eoa/templates/menu/menu.html
@@ -0,0 +1,12 @@
+{% load menu_tags %}
+
+{% for child in children %}
+<li class="nav__item {% if child.selected %}nav__item--active{% endif %}{% if child.ancestor %} ancestor{% endif %}{% if child.sibling %} sibling{% endif %}{% if child.descendant %} descendant{% endif %}">
+  <a class="nav__link {% if child.selected %}nav__link--active{% endif %}" href="{{ child.attr.redirect_url|default:child.get_absolute_url }}">{{ child.get_menu_title }}</a>
+	{% if child.children %}
+	<ul>{{node.title}}fsf
+		{% show_menu from_level to_level extra_inactive extra_active template "" "" child %}
+	</ul>
+	{% endif %}
+</li>
+{% endfor %}
diff --git a/src/eoa/urls.py b/src/eoa/urls.py
index e7ddb02..80146d4 100644
--- a/src/eoa/urls.py
+++ b/src/eoa/urls.py
@@ -13,9 +13,33 @@
     1. Import the include() function: from django.urls import include, path
     2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
 """
+from django.urls import path, include, re_path
 from django.contrib import admin
-from django.urls import path
+
+from cms.sitemaps import CMSSitemap
+from django.conf import settings
+from django.contrib.sitemaps.views import sitemap
+from django.contrib.staticfiles.urls import staticfiles_urlpatterns
+from django.views.static import serve
+
+admin.autodiscover()
 
 urlpatterns = [
+    path('', include('eoapublications.urls')),
+    path('opds/', include('opds.urls')),
+    path(r'sitemap.xml', sitemap,
+        {'sitemaps': {'cmspages': CMSSitemap}}),
+]
+
+# https://stackoverflow.com/questions/17959941/how-to-remove-the-language-identifier-from-django-cms-2-4-urls
+urlpatterns += [
     path('admin/', admin.site.urls),
+    path('', include('cms.urls')),
 ]
+
+# This is only needed when using runserver.
+if settings.DEBUG:
+    urlpatterns = [
+        re_path(r'^media/(?P<path>.*)$', serve,
+            {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}),
+        ] + staticfiles_urlpatterns() + urlpatterns