diff --git a/static/js.cookie.js b/static/js.cookie.js
new file mode 100644
index 0000000000000000000000000000000000000000..12fa0eebf46b07d7c79926b67af75ccdd381d30e
--- /dev/null
+++ b/static/js.cookie.js
@@ -0,0 +1,156 @@
+/*!
+ * JavaScript Cookie v2.1.3
+ * https://github.com/js-cookie/js-cookie
+ *
+ * Copyright 2006, 2015 Klaus Hartl & Fagner Brack
+ * Released under the MIT license
+ */
+;(function (factory) {
+	var registeredInModuleLoader = false;
+	if (typeof define === 'function' && define.amd) {
+		define(factory);
+		registeredInModuleLoader = true;
+	}
+	if (typeof exports === 'object') {
+		module.exports = factory();
+		registeredInModuleLoader = true;
+	}
+	if (!registeredInModuleLoader) {
+		var OldCookies = window.Cookies;
+		var api = window.Cookies = factory();
+		api.noConflict = function () {
+			window.Cookies = OldCookies;
+			return api;
+		};
+	}
+}(function () {
+	function extend () {
+		var i = 0;
+		var result = {};
+		for (; i < arguments.length; i++) {
+			var attributes = arguments[ i ];
+			for (var key in attributes) {
+				result[key] = attributes[key];
+			}
+		}
+		return result;
+	}
+
+	function init (converter) {
+		function api (key, value, attributes) {
+			var result;
+			if (typeof document === 'undefined') {
+				return;
+			}
+
+			// Write
+
+			if (arguments.length > 1) {
+				attributes = extend({
+					path: '/'
+				}, api.defaults, attributes);
+
+				if (typeof attributes.expires === 'number') {
+					var expires = new Date();
+					expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
+					attributes.expires = expires;
+				}
+
+				try {
+					result = JSON.stringify(value);
+					if (/^[\{\[]/.test(result)) {
+						value = result;
+					}
+				} catch (e) {}
+
+				if (!converter.write) {
+					value = encodeURIComponent(String(value))
+						.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
+				} else {
+					value = converter.write(value, key);
+				}
+
+				key = encodeURIComponent(String(key));
+				key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
+				key = key.replace(/[\(\)]/g, escape);
+
+				return (document.cookie = [
+					key, '=', value,
+					attributes.expires ? '; expires=' + attributes.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
+					attributes.path ? '; path=' + attributes.path : '',
+					attributes.domain ? '; domain=' + attributes.domain : '',
+					attributes.secure ? '; secure' : ''
+				].join(''));
+			}
+
+			// Read
+
+			if (!key) {
+				result = {};
+			}
+
+			// To prevent the for loop in the first place assign an empty array
+			// in case there are no cookies at all. Also prevents odd result when
+			// calling "get()"
+			var cookies = document.cookie ? document.cookie.split('; ') : [];
+			var rdecode = /(%[0-9A-Z]{2})+/g;
+			var i = 0;
+
+			for (; i < cookies.length; i++) {
+				var parts = cookies[i].split('=');
+				var cookie = parts.slice(1).join('=');
+
+				if (cookie.charAt(0) === '"') {
+					cookie = cookie.slice(1, -1);
+				}
+
+				try {
+					var name = parts[0].replace(rdecode, decodeURIComponent);
+					cookie = converter.read ?
+						converter.read(cookie, name) : converter(cookie, name) ||
+						cookie.replace(rdecode, decodeURIComponent);
+
+					if (this.json) {
+						try {
+							cookie = JSON.parse(cookie);
+						} catch (e) {}
+					}
+
+					if (key === name) {
+						result = cookie;
+						break;
+					}
+
+					if (!key) {
+						result[name] = cookie;
+					}
+				} catch (e) {}
+			}
+
+			return result;
+		}
+
+		api.set = api;
+		api.get = function (key) {
+			return api.call(api, key);
+		};
+		api.getJSON = function () {
+			return api.apply({
+				json: true
+			}, [].slice.call(arguments));
+		};
+		api.defaults = {};
+
+		api.remove = function (key, attributes) {
+			api(key, '', extend(attributes, {
+				expires: -1
+			}));
+		};
+
+		api.withConverter = init;
+
+		return api;
+	}
+
+	return init(function () {});
+}));
diff --git a/templates/base.html b/templates/base.html
index 0b5d4caae7ea805bafabd07e5fe24413b580f39d..079d5cff5fad096052542bbf37f38665cd30bf41 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -8,16 +8,19 @@
 	<head>
 		<title>Video AG</title>
 		<meta http-equiv="X-UA-Compatible" content="IE=edge">
-		<script src="{{url_for('static', filename='jquery.js')}}"></script>
-		<link rel="stylesheet" type="text/css" href="{{url_for('static', filename='style.css')}}">
-		<link rel="stylesheet" href="{{url_for('static', filename='font-awesome/css/font-awesome.min.css')}}">
 		<link rel="icon" type="image/png" href="{{url_for('static', filename='favicon.png')}}">
 		<meta http-equiv="content-language" content="de-DE">
 		<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
 		<meta charset="UTF-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1">
+
 		<link href="{{url_for('static', filename='bootstrap/bootstrap.css')}}" rel="stylesheet">
+		<link rel="stylesheet" type="text/css" href="{{url_for('static', filename='style.css')}}">
+		<link rel="stylesheet" href="{{url_for('static', filename='font-awesome/css/font-awesome.min.css')}}">
+
+		<script src="{{url_for('static', filename='jquery.js')}}"></script>
 		<script src="{{url_for('static', filename='bootstrap/bootstrap.js')}}"></script>
+		<script src="{{url_for('static', filename='js.cookie.js')}}"></script>
 		{%if ismod() %}<script src="{{url_for('static', filename='moderator.js')}}"></script>{% endif %}
 	</head>
 	<body>
@@ -105,8 +108,10 @@
 					{% for msg in get_flashed_messages() %}
 					<div class="alert alert-danger" role="alert">{{ msg }}</div>
 					{% endfor %}
-					{% for msg in get_announcements(min_announcement_level) %}
+					{% for msg in get_announcements(min_announcement_level) if (not request.cookies['alert-info-'+msg.id|string]) or ismod() %}
 					<div class="alert alert-{{announcement_levels.get(msg.level, 'info')}}" role="alert">
+						<a href="#" class="close" data-dismiss="alert" aria-label="close" onclick="Cookies.set('alert-info-{{msg.id}}', '1');">&times;</a>
+
 						{{ valueeditor(('announcements',msg.id,'text'), msg.text|safe) }}
 						{% if ismod() %}
 						<div class="pull-right">
diff --git a/templates/lecture.html b/templates/lecture.html
index 2f6ae671c3ce9ecb604cbb002d3d434c9a0d71ee..8c10cea3938669e9094248ef580cb99b44043028 100644
--- a/templates/lecture.html
+++ b/templates/lecture.html
@@ -7,7 +7,7 @@
 {% block content %}
 <div class="panel panel-default">
 	<div class="panel-heading">
-		<h1 class="panel-title"><strong>{{ course.title }}</strong>: {{ lecture.title}}</h1>
+		<h1 class="panel-title"><strong><a href="{{url_for('course', handle=course.handle)}}#lecture-{{lecture.id}}">{{ course.title }}</strong></a>: {{ lecture.title}}</h1>
 	</div>
 	<div class="panel-body">
 		<div class="row" style="padding: 0px;">
diff --git a/templates/macros.html b/templates/macros.html
index f41dcb06f7a3c4c9e254eae809e6eb13dc6daddb..6e1b722e8e154c9b9bfc7c5113773e77233fdced 100644
--- a/templates/macros.html
+++ b/templates/macros.html
@@ -2,7 +2,7 @@
 <li class="list-group-item">
 	<a class="hidden-xs" href="{{url_for('lecture', id=lecture['id'])}}" title="{{ lecture['coursetitle'] }}" style="color: #000">
 		<div class="row">
-			<img class="col-xs-4" style="max-height: 100px; width: auto;" src="{{ config.VIDEOPREFIX }}/{{ lecture['titlefile'] }}" alt="Vorschaubild" onerror="this.src='{{url_for('static',filename='no-thumbnail.png')}}'">
+			<img class="col-xs-4" style="max-height: 100px; width: auto;" src="{{ config.VIDEOPREFIX }}/{{ lecture['titlefile'] }}" alt="Vorschaubild" onerror="this.src='{{url_for('static',filename='no-thumbnail.png')}}'; this.onerror=''; ">
 			<div class="col-xs-4">
 				<span><strong>{{ lecture['short'] }}</strong></span><br>
 				<span>{{ lecture['time'] }}</span>
@@ -19,7 +19,7 @@
 	<a class="visible-xs" href="{{url_for('lecture', id=lecture['id'])}}" title="{{ lecture['coursetitle'] }}" style="color: #000">
 		<ul class="list-unstyled">
 			<li>
-				<img style="width: 100%;" src="{{ config.VIDEOPREFIX }}/{{ lecture['titlefile'] }}" alt="Vorschaubild" onerror="this.src='{{url_for('static',filename='no-thumbnail.png')}}'">
+				<img style="width: 100%;" src="{{ config.VIDEOPREFIX }}/{{ lecture['titlefile'] }}" alt="Vorschaubild" onerror="this.src='{{url_for('static',filename='no-thumbnail.png')}}'; this.onerror=''; ">
 			</li>
 			<li>
 				<strong>{{ lecture['short'] }}</strong>	{{ lecture['time'] }}
@@ -65,7 +65,6 @@
 {% macro course_list_item(course,show_semester=False) %}
 <li class="list-group-item list-group-item-condensed {% if (not course.visible) or (not course.listed) %}list-group-item-danger{% endif %}">
 	<div class="row">
-		<a href="{{url_for('course', handle=course.handle)}}">
 			{% if show_semester %}
 				<span class="col-xs-2 col-md-1">
 					{{ course.semester }}
@@ -74,7 +73,9 @@
 			{% else %}
 				<span class="col-xs-12 col-md-7">
 			{% endif %}
+				<a href="{{url_for('course', handle=course.handle)}}">
 				{{ course.title }}
+				</a>
 			</span>
 			<span class="col-xs-8 col-md-3">
 				{{ course.organizer }}
@@ -82,7 +83,6 @@
 			<span class="col-xs-4 col-md-2">
 				{{ course.subject }}
 			</span>
-		</a>
 	</div>
 </li>
 {% endmacro %}
@@ -124,7 +124,7 @@ $('#embedcodebtn').popover(
 {% macro lecture_list_item(lecture,videos) %}
 <li class="list-group-item" id="lecture-{{lecture.id}}">
 	<div class="row">
-		<img class="col-sm-2 col-xs-12"src="{{ config.VIDEOPREFIX }}/{{lecture.titlefile}}" alt="Vorschaubild" onerror="this.src='{{url_for('static',filename='no-thumbnail.png')}}'">
+		<img class="col-sm-2 col-xs-12"src="{{ config.VIDEOPREFIX }}/{{lecture.titlefile}}" alt="Vorschaubild" onerror="this.src='{{url_for('static',filename='no-thumbnail.png')}}'; this.onerror=''; ">
 		<span class="col-sm-3 col-xs-12">
 			<ul class="list-unstyled">
 				<li>{{ valueeditor(['lectures',lecture.id,'title'], lecture.title) }}</li>