diff --git a/server.py b/server.py
index 38bb07873ae5402f66faa1e65d31ed22f06694e6..05c8d4172793c6a7f7b93e83e986e157462890cc 100755
--- a/server.py
+++ b/server.py
@@ -15,9 +15,9 @@ from datetime import datetime
 
 import config
 from shared import db, date_filter, datetime_filter, date_filter_long, time_filter, ldap_manager, security_manager, current_user, check_login, login_required, group_required
-from utils import is_past, mail_manager, url_manager
+from utils import is_past, mail_manager, url_manager, get_first_unused_int
 from models.database import ProtocolType, Protocol, DefaultTOP, TOP, Document, Todo, Decision, MeetingReminder, Error
-from views.forms import LoginForm, ProtocolTypeForm, DefaultTopForm, MeetingReminderForm, NewProtocolForm, DocumentUploadForm, KnownProtocolSourceUploadForm, NewProtocolSourceUploadForm, ProtocolForm
+from views.forms import LoginForm, ProtocolTypeForm, DefaultTopForm, MeetingReminderForm, NewProtocolForm, DocumentUploadForm, KnownProtocolSourceUploadForm, NewProtocolSourceUploadForm, ProtocolForm, TopForm
 from views.tables import ProtocolsTable, ProtocolTypesTable, ProtocolTypeTable, DefaultTOPsTable, MeetingRemindersTable, ErrorsTable, TodosTable, DocumentsTable
 
 app = Flask(__name__)
@@ -188,7 +188,6 @@ def delete_reminder(type_id, reminder_id):
     db.session.commit()
     return redirect(request.args.get("next") or url_for("show_type", type_id=protocoltype.id))
 
-
 @app.route("/type/tops/new/<int:type_id>", methods=["GET", "POST"])
 @login_required
 def new_default_top(type_id):
@@ -265,8 +264,11 @@ def move_default_top(type_id, top_id, diff):
     if default_top is None or default_top.protocoltype != protocoltype:
         flash("Invalider Standard-TOP.", "alert-error")
         return redirect(request.args.get("next") or url_for("index"))
-    default_top.number += int(diff)
-    db.session.commit()
+    try:
+        default_top.number += int(diff)
+        db.session.commit()
+    except ValueError:
+        flash("Die angegebene Differenz ist keine Zahl.", "alert-error")
     return redirect(request.args.get("next") or url_for("show_type", type_id=protocoltype.id))
 
 
@@ -425,9 +427,6 @@ def upload_new_protocol():
                     tasks.parse_protocol(protocol)
                     return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=protocol.id))
     return redirect(request.args.get("fail") or url_for("new_protocol"))
-        
-    
-
 
 @app.route("/protocol/source/<int:protocol_id>")
 @login_required
@@ -452,6 +451,73 @@ def update_protocol(protocol_id):
     edit_form = ProtocolForm(obj=protocol)
     return render_template("protocol-update.html", upload_form=upload_form, edit_form=edit_form, protocol=protocol)
 
+@app.route("/protocol/tops/new/<int:protocol_id>", methods=["GET", "POST"])
+@login_required
+def new_top(protocol_id):
+    user = current_user()
+    protocol = Protocol.query.filter_by(id=protocol_id).first()
+    if protocol is None or not protocol.protocoltype.has_modify_right(user):
+        flash("Invalides Protokoll oder keine Berechtigung.", "alert-error")
+        return redirect(request.args.get("next") or url_for("index"))
+    form = TopForm()
+    if form.validate_on_submit():
+        top = TOP(protocol_id=protocol.id, name=form.name.data, number=form.number.data, planned=True)
+        db.session.add(top)
+        db.session.commit()
+        return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=protocol.id))
+    else:
+        print(form.number.data)
+        current_numbers = list(map(lambda t: t.number, protocol.tops))
+        suggested_number = get_first_unused_int(current_numbers)
+        form.number.data = suggested_number
+    return render_template("top-new.html", form=form, protocol=protocol)
+
+@app.route("/protocol/top/edit/<int:top_id>", methods=["GET", "POST"])
+@login_required
+def edit_top(top_id):
+    user = current_user()
+    top = TOP.query.filter_by(id=top_id).first()
+    if top is None or not top.protocol.protocoltype.has_modify_right(user):
+        flash("Invalider TOP oder keine Berechtigung.", "alert-error")
+        return redirect(request.args.get("next") or url_for("index"))
+    form = TopForm(obj=top)
+    if form.validate_on_submit():
+        form.populate_obj(top)
+        db.session.commit()
+        return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=top.protocol.id))
+    return render_template("top-edit.html", form=form, top=top)
+
+@app.route("/protocol/top/delete/<int:top_id>")
+@login_required
+def delete_top(top_id):
+    user = current_user()
+    top = TOP.query.filter_by(id=top_id).first()
+    if top is None or not top.protocol.protocoltype.has_modify_right(user):
+        flash("Invalider TOP oder keine Berechtigung.", "alert-error")
+        return redirect(request.args.get("next") or url_for("index"))
+    name = top.name
+    protocol_id = top.protocol.id
+    db.session.delete(top)
+    db.session.commit()
+    flash("Der TOP {} wurde gelöscht.".format(name), "alert-success")
+    return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=protocol_id))
+
+@app.route("/protocol/top/move/<int:top_id>/<diff>")
+@login_required
+def move_top(top_id, diff):
+    user = current_user()
+    top = TOP.query.filter_by(id=top_id).first()
+    if top is None or not top.protocol.protocoltype.has_modify_right(user):
+        flash("Invalider TOP oder keine Berechtigung.", "alert-error")
+        return redirect(request.args.get("next") or url_for("index"))
+    try:
+        top.number += int(diff)
+        db.session.commit()
+    except ValueError:
+        flash("Die angegebene Differenz ist keine Zahl.", "alert-error")
+    return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=top.protocol.id))
+        
+
 @app.route("/todos/list")
 def list_todos():
     is_logged_in = check_login()
diff --git a/shared.py b/shared.py
index b58cf3219bd11fe858f7bf6931980dae69648e6c..9761b10c54092fa978f5ea3a49801aeb9963941f 100644
--- a/shared.py
+++ b/shared.py
@@ -111,3 +111,9 @@ def group_required(function, group):
             return redirect(request.args.get("next") or url_for("index"))
     return decorated_function
 
+EMPTY_ETHERPAD = """Welcome to Etherpad!
+
+This pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!
+
+Get involved with Etherpad at http://etherpad.org
+"""
diff --git a/templates/protocol-show.html b/templates/protocol-show.html
index d9bde019c5c4de308d263a7e2df3c1f6f59540e5..1bb9db94ff79269fbf8784d4d5a7845109d5b50a 100644
--- a/templates/protocol-show.html
+++ b/templates/protocol-show.html
@@ -2,10 +2,16 @@
 {% from "macros.html" import render_table, render_form %}
 {% block title %}Protokoll{% endblock %}
 
+{% set loggedin = check_login() %}
+{% set user = current_user() %}
+{% set has_public_view_right = protocol.protocoltype.has_public_view_right(user) %}
+{% set has_private_view_right = protocol.protocoltype.has_private_view_right(user) %}
+{% set has_modify_right = protocol.protocoltype.has_modify_right(user) %}
+
 {% block content %}
 <div class="container">
     <div class="btn-group">
-        {% if protocol.protocoltype.has_modify_right(current_user()) %}
+        {% if has_modify_right %}
             <a class="btn {% if protocol.source is none %}btn-primary{% else %}btn-default{% endif %}" href="{{url_for("etherpull_protocol", protocol_id=protocol.id)}}">From etherpad</a>
             {% if protocol.source is not none %}
                 <a class="btn btn-primary" href="{{url_for("get_protocol_source", protocol_id=protocol.id)}}">Download Quelltext</a>
@@ -39,26 +45,8 @@
                 {% if protocol.date is not none %}<p><strong>Geplant:</strong> {{protocol.date|datify_long}}{% endif %}</p>
             {% endif %}
 
-            <h3>Tagesordnung</h3>
-            <ul>
-            {% if not protocol.has_nonplanned_tops() %}
-                {% for default_top in protocol.protocoltype.default_tops %}
-                    {% if not default_top.is_at_end() %}
-                        <li>{{default_top.name}}</li>
-                    {% endif %}
-                {% endfor %}
-            {% endif %}
-            {% for top in protocol.tops %}
-                <li>{{top.name}}</li>
-            {% endfor %}
-            {% if not protocol.has_nonplanned_tops() %}
-                {% for default_top in protocol.protocoltype.default_tops %}
-                    {% if default_top.is_at_end() %}
-                        <li>{{default_top.name}}</li>
-                    {% endif %}
-                {% endfor %}
-            {% endif %}
-            </ul>
+            <h3>Tagesordnung{% if has_modify_right and not protocol.has_nonplanned_tops() %} <a href="{{url_for("new_top", protocol_id=protocol.id)}}">Top hinzufügen</a>{% endif %}</h3>
+            {% include "protocol-tops-include.html" %}
 
             {% if protocol.is_done() %}
             <h3>Beschlüsse</h3>
@@ -82,7 +70,7 @@
                     {% endif %}
                 </ul>
             {% endif %}
-            {% if protocol.protocoltype.has_modify_right(current_user()) %}
+            {% if has_modify_right %}
                 {% if protocol.errors|length > 0 %}
                     {{render_table(errors_table)}}
                 {% endif %}
@@ -90,9 +78,11 @@
             {% if protocol.documents|length > 0 %}
                 {{render_table(documents_table)}}
             {% else %}
-                <h3>Hochladen</h3>
+                {% if has_modify_right %}
+                    <h3>Hochladen</h3>
+                {% endif %}
             {% endif %}
-            {% if protocol.protocoltype.has_modify_right(current_user()) %}
+            {% if has_modify_right %}
             {{render_form(source_upload_form, action_url=url_for("upload_source_to_known_protocol", protocol_id=protocol.id, next=url_for("show_protocol", protocol_id=protocol.id)), action_text="Hochladen", enctype="multipart/form-data")}}
             {{render_form(document_upload_form, action_url=url_for("upload_document", protocol_id=protocol.id, next=url_for("show_protocol", protocol_id=protocol.id)), action_text="Hochladen", enctype="multipart/form-data")}}
             {% endif %}
diff --git a/templates/protocol-tops-include.html b/templates/protocol-tops-include.html
new file mode 100644
index 0000000000000000000000000000000000000000..ca9a0a63c76463789e1f57e0ee5fb7de27911b04
--- /dev/null
+++ b/templates/protocol-tops-include.html
@@ -0,0 +1,30 @@
+<ul>
+    {% if not protocol.has_nonplanned_tops() %}
+        {% for default_top in protocol.protocoltype.default_tops %}
+            {% if not default_top.is_at_end() %}
+                <li>{{default_top.name}}</li>
+            {% endif %}
+        {% endfor %}
+    {% endif %}
+    {% for top in protocol.tops %}
+        <li>
+            {{top.name}}
+            {% if has_private_view_right %}
+                ({{top.number}})
+            {% endif %}
+            {% if has_modify_right %}
+                <a href="{{url_for('edit_top', top_id=top.id)}}">Ändern</a>
+                <a href="{{url_for('move_top', top_id=top.id, diff=1)}}">Runter</a>
+                <a href="{{url_for('move_top', top_id=top.id, diff=-1)}}">Hoch</a>
+                <a href="{{url_for('delete_top', top_id=top.id)}}" onclick="return confirm('Bist du dir sicher, dass du den TOP {{top.name}} löschen möchtest?');">Löschen</a>
+            {% endif %}
+        </li>
+    {% endfor %}
+    {% if not protocol.has_nonplanned_tops() %}
+        {% for default_top in protocol.protocoltype.default_tops %}
+            {% if default_top.is_at_end() %}
+                <li>{{default_top.name}}</li>
+            {% endif %}
+        {% endfor %}
+    {% endif %}
+</ul>
diff --git a/templates/top-edit.html b/templates/top-edit.html
new file mode 100644
index 0000000000000000000000000000000000000000..31e56b9afd9ffc1435d9f52bd0a523fdd4932da8
--- /dev/null
+++ b/templates/top-edit.html
@@ -0,0 +1,9 @@
+{% extends "layout.html" %}
+{% from "macros.html" import render_form %}
+{% block title %}TOP bearbeiten{% endblock %}
+
+{% block content %}
+<div class="container">
+    {{render_form(form, action_url=url_for("edit_top", top_id=top.id, next=request.args.get("next") or url_for("show_protocol", protocol_id=top.protocol.id)), action_text="Ändern")}}
+</div>
+{% endblock %}
diff --git a/templates/top-new.html b/templates/top-new.html
new file mode 100644
index 0000000000000000000000000000000000000000..3b604d0fb68d5b041a6aed4b5a911acb4fa820bd
--- /dev/null
+++ b/templates/top-new.html
@@ -0,0 +1,24 @@
+{% extends "layout.html" %}
+{% from "macros.html" import render_form %}
+{% block title %}TOP hinzufügen{% endblock %}
+
+{% set loggedin = check_login() %}
+{% set user = current_user() %}
+{% set has_public_view_right = protocol.protocoltype.has_public_view_right(user) %}
+{% set has_private_view_right = protocol.protocoltype.has_private_view_right(user) %}
+{% set has_modify_right = protocol.protocoltype.has_modify_right(user) %}
+
+{% block content %}
+<div class="container">
+    <div class="row">
+        <div id="left-column" class="col-lg-6">
+            <h3>Tagesordnung</h3>
+            {% include "protocol-tops-include.html" %}
+        </div>
+        <div id="right-column" class="col-lg-6">
+            <h3>TOP hinzufügen</h3>
+            {{render_form(form, action_url=url_for("new_top", protocol_id=protocol.id, next=url_for("show_protocol", protocol_id=protocol.id)), action_text="Anlegen")}}
+        </div>
+    </div>
+</div>
+{% endblock %}
diff --git a/utils.py b/utils.py
index b1cd9f733acd060f659a27390f3059b5a70f23ec..47738f34704e7782ae55291ae7548adefc385a00 100644
--- a/utils.py
+++ b/utils.py
@@ -90,3 +90,13 @@ class MailManager:
         return True
 
 mail_manager = MailManager(config)
+
+def get_first_unused_int(numbers):
+    positive_numbers = [number for number in numbers if number >= 0]
+    if len(positive_numbers) == 0:
+        return 0
+    highest = max(positive_numbers)
+    for given, linear in zip(positive_numbers, range(highest+1)):
+        if linear < given:
+            return linear
+    return highest + 1
diff --git a/views/forms.py b/views/forms.py
index 5474a328e298bf63778bec3e9ad5c34b1f79c008..a8303bf4448c4ac268cc7ee3df7c9b0a93ec9900 100644
--- a/views/forms.py
+++ b/views/forms.py
@@ -57,3 +57,7 @@ class ProtocolForm(FlaskForm):
     participants = StringField("Anwesende")
     done = BooleanField("Fertig")
 
+class TopForm(FlaskForm):
+    name = StringField("TOP", validators=[InputRequired("Du musst den Namen des TOPs angeben.")])
+    number = IntegerField("Sortierung", validators=[InputRequired("Du musst eine Sortierung in der Reihenfolge angebene.")])
+