diff --git a/auth.py b/auth.py
index 1faf872c8e8e01ef1ad6623a19a85d8a457c6545..23d5a153c026a922e5fd0f49af331f0943408079 100644
--- a/auth.py
+++ b/auth.py
@@ -29,7 +29,6 @@ class LdapManager:
         if not self.authenticate(username, password):
             return None
         groups = list(map(lambda g: g.decode("utf-8"), self.groups(username)))
-        print(groups)
         return User(username, groups)
 
     def authenticate(self, username, password):
diff --git a/server.py b/server.py
index c5385205793ff48453150569cb8b443d66038265..b2c684904532d3dcf0d0877bc20985ec0ace10dd 100755
--- a/server.py
+++ b/server.py
@@ -12,7 +12,9 @@ from functools import wraps
 import config
 from shared import db, date_filter, datetime_filter, ldap_manager, security_manager
 from utils import is_past, mail_manager, url_manager
+from models.database import ProtocolType, Protocol, DefaultTOP, TOP, Document, Todo, Decision, MeetingReminder, Error
 from views.forms import LoginForm
+from views.tables import ProtocolsTable
 
 app = Flask(__name__)
 app.config.from_object(config)
@@ -65,10 +67,24 @@ app.jinja_env.globals.update(current_user=current_user)
 # blueprints here
 
 @app.route("/")
-@login_required
+#@login_required
 def index():
     return render_template("index.html")
 
+@app.route("/protocol/list")
+def list_protocols():
+    is_logged_in = check_login()
+    user = current_user()
+    protocols = [
+        protocol for protocol in Protocol.query.all()
+        if (not is_logged_in and protocol.protocoltype.is_public)
+        or (is_logged_in and (
+            protocol.protocoltype.public_group in user.groups
+            or protocol.protocoltype.private_group in user.groups))]
+    protocols_table = ProtocolsTable(protocols)
+    return render_template("protocol-list.html", protocols=protocols, protocols_table=protocols_table)
+    
+
 @app.route("/login", methods=["GET", "POST"])
 def login():
     if "auth" in session:
diff --git a/templates/layout.html b/templates/layout.html
index 95c63bd1ef62de301888445121cc4f0483015fdb..31b61d5004c91fbf4dff7c97a9421c8fd8158a34 100644
--- a/templates/layout.html
+++ b/templates/layout.html
@@ -27,6 +27,7 @@
         <div id="navbar" class="navbar-collapse collapse">
             <ul class="nav navbar-nav">
                 <li><a href="{{url_for("index")}}">Zuhause</a></li>
+                <li><a href="{{url_for("list_protocols")}}">Protokolle</a></li>
                 {# todo: add more links #}
             </ul>
             <ul class="nav navbar-nav navbar-right">
diff --git a/templates/login.html b/templates/login.html
index fa86d85d59518580a5205050809aa05d7cdd3cc1..3948f977923683a47bf6d022675d991659721315 100644
--- a/templates/login.html
+++ b/templates/login.html
@@ -3,5 +3,7 @@
 {% block title %}Login{% endblock %}
 
 {% block content %}
+<div class="container">
     {{render_form(form)}}
+</div>
 {% endblock %}
diff --git a/templates/macros.html b/templates/macros.html
index bc416ca5b18255e28a0a76d8e922b62f4e7062e6..8ef7e6e41fec0b769f3b7cc610978c4787a8226c 100644
--- a/templates/macros.html
+++ b/templates/macros.html
@@ -107,3 +107,24 @@ to not render a label for the CRSFTokenField -->
         <button type="submit" class="{{ btn_class }}">{{ action_text }} </button>
     </form>
 {%- endmacro %}
+
+{% macro render_table(table) -%}
+    <table class="table table-striped">
+        <thead>
+            <tr>
+                {% for header in table.headers() %}
+                    <th>{{header}}</th>
+                {% endfor %}
+            </tr>
+        </thead>
+        <tbody>
+            {% for row in table.rows() %}
+                <tr>
+                    {% for entry in row %}
+                        <td>{{entry}}</td>
+                    {% endfor %}
+                </tr>
+            {% endfor %}
+        </tbody>
+    </table>
+{%- endmacro %}
diff --git a/templates/protocol-list.html b/templates/protocol-list.html
new file mode 100644
index 0000000000000000000000000000000000000000..43d3cdb84bf413a7a4d8a9935b440b2e598a1ebc
--- /dev/null
+++ b/templates/protocol-list.html
@@ -0,0 +1,9 @@
+{% extends "layout.html" %}
+{% from "macros.html" import render_table %}
+{% block title %}Protokolle{% endblock %}
+
+{% block content %}
+<div class="container">
+    {{render_table(protocols_table)}}
+</div>
+{% endblock %}
diff --git a/views/tables.py b/views/tables.py
new file mode 100644
index 0000000000000000000000000000000000000000..bb3a44d4811ad45d0ac265660be172f28fad22c5
--- /dev/null
+++ b/views/tables.py
@@ -0,0 +1,63 @@
+# coding: utf-8
+from flask import Markup, url_for, request
+from models.database import Protocol, ProtocolType, DefaultTOP, TOP, Todo, Decision
+from shared import date_filter
+
+class Table:
+    def __init__(self, title, values, newlink=None):
+        self.title = title
+        self.values = values
+        self.newlink = newlink
+        self.newtext = "New"
+
+    def rows(self):
+        return [row for row in [self.row(value) for value in self.values] if row is not None]
+
+    @staticmethod
+    def link(target, text, confirm=None):
+        confirmation = ""
+        if confirm:
+            confirmation = " onclick=\"return confirm('{}');\"".format(confirm)
+        return Markup("<a href=\"{}\"{}>{}</a>".format(target, confirmation, text))
+
+    @staticmethod
+    def mail(target):
+        return Markup("<a href=\"mailto:{}\">{}</a>".format(target, target))
+
+    @staticmethod
+    def bool(value):
+        return "Yes" if value else "No"
+
+    @staticmethod
+    def concat(values):
+        return ", ".join(values)
+        #if len(values) <= 1:
+        #    return "".join(values)
+        #else:
+        #    return "{} and {}".format(", ".join(values[:-1]), values[-1])
+            
+
+class SingleValueTable:
+    def __init__(self, title, value, newlink=None):
+        self.title = title
+        self.value = value
+        self.newlink = newlink if newlink else None
+        self.newtext = "Edit"
+
+    def rows(self):
+        return [self.row()]
+
+class ProtocolsTable(Table):
+    def __init__(self, protocols):
+        super().__init__("Protokolle", protocols, newlink=None)
+
+    def headers(self):
+        return ["ID", "Sitzung", "Datum"]
+
+    def row(self, protocol):
+        return [
+            Table.link(url_for("protocol_view", protocol_id=protocol.id), str(protocol.id)),
+            protocol.protocoltype.name,
+            date_filter(protocol.data)
+        ]
+