diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..d2241cf6f9a8874b0e828016b4eab8f4969ee964
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,39 @@
+*.py[co]
+
+# Packages
+*.egg
+*.egg-info
+dist
+build
+eggs
+parts
+bin
+var
+sdist
+develop-eggs
+.installed.cfg
+
+# Installer logs
+pip-log.txt
+
+# Unit test / coverage reports
+.coverage
+.tox
+
+#Translations
+*.mo
+
+#Mr Developer
+.mr.developer.cfg
+
+# backup files
+*~
+
+# data files
+savegames
+
+config.py
+schilder.wsgi
+
+*.png.*
+*.schild.*
diff --git a/config.py.example b/config.py.example
index 9b6764099f1e6df91551f3546ebda29668206db2..11696bdf8850916d49b42894842c0ead55fffffd 100755
--- a/config.py.example
+++ b/config.py.example
@@ -33,6 +33,9 @@ pdfdir = datadir + '/pdf'
 # Image data directory (needs to be writeable)
 imagedir = datadir + '/images'
 
+# Cache dir (needs to be writable)
+cachedir = datadir + '/cache'
+
 # Upload temp directory (needs to be writeable)
 uploaddir = datadir + '/upload'
 
diff --git a/data/cache/.gitignore b/data/cache/.gitignore
new file mode 100755
index 0000000000000000000000000000000000000000..7dc49cf8232069216f9a1b31868ada2498ab46c8
--- /dev/null
+++ b/data/cache/.gitignore
@@ -0,0 +1 @@
+*.pdf*
\ No newline at end of file
diff --git a/schilder.py b/schilder.py
index 0b587008b1e022d16ceb862f73ae37321b20f6f6..0af3387548d241d459be502e615b94342c3e1f10 100755
--- a/schilder.py
+++ b/schilder.py
@@ -85,11 +85,13 @@ def edit_one(filename):
     formdata = json.load(infile)
     return edit(form=formdata)
 
-def run_pdflatex(context, outputfilename):
+def run_pdflatex(context, outputfilename, overwrite=True):
   if not context.has_key('textemplate'):
     context['textemplate'] = "text-image-quer.tex"
   genshitex = TemplateLoader([config.textemplatedir])
   template = genshitex.load(context['textemplate'], cls=NewTextTemplate, encoding='utf8')
+  if not overwrite and os.path.isfile(outputfilename) and os.path.getmtime(template.filepath) < os.path.getmtime(outputfilename):
+      return
   tmpdir = tempfile.mkdtemp(dir=config.tmpdir)
   if context.has_key('img') and context['img'] and context['img'] != '__none':
     try:
@@ -109,11 +111,13 @@ def run_pdflatex(context, outputfilename):
   try:
     texlog = check_output(['pdflatex', '--halt-on-error', tmptexfile], stderr=STDOUT)
   except CalledProcessError as e:
-    flash(Markup("<p>PDFLaTeX Output:</p><pre>%s</pre>" % e.output), 'log')
+    if overwrite:
+        flash(Markup("<p>PDFLaTeX Output:</p><pre>%s</pre>" % e.output), 'log')
     raise SyntaxWarning("PDFLaTeX bailed out")
   finally:
     os.chdir(cwd)
-  flash(Markup("<p>PDFLaTeX Output:</p><pre>%s</pre>" % texlog), 'log')
+  if overwrite:
+    flash(Markup("<p>PDFLaTeX Output:</p><pre>%s</pre>" % texlog), 'log')
   shutil.copy(tmppdffile, outputfilename)
   shutil.rmtree(tmpdir)
 
@@ -229,6 +233,24 @@ def pdfthumbnail(pdfname, maxgeometry):
   with open(thumbpath, 'r') as imgfile:
     return Response(imgfile.read(), mimetype="image/png")
 
+@app.route('/tplthumb/<tplname>/<int:maxgeometry>')
+def tplthumbnail(tplname, maxgeometry):
+  pdfpath = os.path.join(config.cachedir, secure_filename(tplname)+'.pdf')
+  try:
+    run_pdflatex(
+      { 'textemplate' : secure_filename(tplname),
+        'img'         : 'pictograms-nps-misc-camera.png',
+        'headline'    : u'Überschrift',
+        'text'        : u'Dies ist der Text, der in der UI als Text bezeichnet ist.',
+      }, pdfpath, overwrite=False
+    )
+  except Exception as e:
+    return str(e)
+  else:
+    thumbpath = make_thumb(pdfpath, maxgeometry)
+    with open(thumbpath, 'r') as imgfile:
+      return Response(imgfile.read(), mimetype="image/png")
+
 @app.route('/pdfdownload/<pdfname>')
 def pdfdownload(pdfname):
   pdfpath = os.path.join(config.pdfdir, secure_filename(pdfname))
diff --git a/static/main.css b/static/main.css
index 0c7907b5f3e6b621177790ae3ebff0148545a0ca..0f163cfa7f1e7779291913ecff91803c2118fea0 100644
--- a/static/main.css
+++ b/static/main.css
@@ -82,6 +82,9 @@ form {
 	margin-top:1em;
 	margin-bottom:1em;
 }
+form ul {
+	padding: 0;
+}
 form li {
 	list-style-type:none;
 	display: inline-block;
@@ -89,17 +92,17 @@ form li {
 input[type="radio"] {
 	position:relative;
 	z-index:5;
-	margin-bottom:1em;
+	margin-bottom:0;
 }
 input[type="radio"]+label > img {
 	position:relative;
 	z-index:4;
-	top:0.5em;
-	left:-1.5em;
+	top:0;
+	left:-1.4em;
 	margin-right:-1.2em;
 	max-width: 100%;
 	max-height: 10em;
-	border:3px solid #eee;
+	border:3px solid lightgray;
 	border-radius: 5px;
 }
 input[type="radio"]:checked+label > img {
@@ -114,3 +117,14 @@ input[type="radio"]:checked + input[type="file"] {
 input[type="radio"]:checked + input[type="file"] + label {
 	display:none;
 }
+textarea {
+    display: block;
+}
+.box {
+    display: inline-block;
+    background: #eee;
+    border: 1px solid lightgray;
+    border-radius: 5px;
+    padding: 0.5em;
+    margin: 1em 0;
+}
diff --git a/templates/edit.html b/templates/edit.html
index f0ad350dce9b9b181763477c67d4932608283a51..f3a3dc7d93cef29e5d0a9427d442d5543d3c00a4 100644
--- a/templates/edit.html
+++ b/templates/edit.html
@@ -2,84 +2,97 @@
 <!-- <html xmlns="http://www.w3.org/1999/xhtml" > -->
 <html xmlns:py="http://genshi.edgewall.org/">
 <head>
-	<link rel='stylesheet' type='text/css' href="${ url_for('static', filename='main.css') }"/>
-	<meta name="viewport" content="width=device-width, initial-scale=1"/>
-	<title>Schildergenerator</title>
+    <link rel='stylesheet' type='text/css' href="${ url_for('static', filename='main.css') }"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1"/>
+    <title>Schildergenerator</title>
 </head>
 <body>
-	<py:with vars="messages = get_flashed_messages(with_categories=True)">
-  		<ul class="flashes" py:if="messages">
-			<li class="${ category }" py:for="category,message in messages" tabindex="0">${ message }</li>
-		</ul>
-	</py:with>
-	<a href="${ url_for('index') }">Liste der fertigen Schilder</a>
-	
-	<form method="post" action="${ url_for('create') }" enctype="multipart/form-data">
-		<label for="form:headline">Großer Text</label>
-		<textarea name="headline" id="form:headline" cols="35" rows="5"><py:if test="defined('form')">${form.headline}</py:if></textarea>
-		<label for="form:text">Zusatztext</label>
-		<textarea name="text" id="form:text" cols="35" rows="5"><py:if test="defined('form')">${form.text}</py:if></textarea>
-		<label for="form:template">TeX-Vorlage</label>
-		<select name="textemplate" id="form:template">	
-			<py:choose>
-				<py:when test="defined('form')">
-				<py:for each="template in templates">
-                                        <py:choose>
-                                                <py:when test="template == form.textemplate">
-                                                        <option label="${template}" value="${template}" selected="selected">${template}</option>
-
-                                                </py:when>
-                                                <py:otherwise>
-                                                        <option label="${template}" value="${template}">${template}</option>
-                                                        
-                                                </py:otherwise>
-                                        </py:choose>
-                                </py:for>
-				</py:when>
-				<py:otherwise>
-					<option py:for="tpl in templates" label="${tpl}" value="${tpl}">${tpl}</option>
-				</py:otherwise>
-			</py:choose>
-		</select>	
-		<ul>
-			<li>
-				<py:choose>
-                                        <py:when test="defined('form')">
-                                                <input type="radio" name="img" id="img--none" value="__none" checked="${form.img == '__none'}"/>
-                                        </py:when>
-                                        <py:otherwise>
-                                                <input type="radio" name="img" id="img--none" value="__none" checked="checked" />
-                                        </py:otherwise>
-				</py:choose>
-				<label for="img--none">Kein Bild</label>
-			</li>
-			<li>
-				<input type="radio" name="img" id="img--upload" value="__upload"/>
-				<input type="file" name="imgupload"/>
-				<label for="img--upload">Bild hochladen</label>
-			</li>
-		</ul>
-		<ul>
-			<li py:for="img in images">
-				<py:choose>
-					<py:when test="defined('form')">
-						<py:choose>
-							<py:when test="img == form.img">
-								<input type="radio" name="img" id="img:${img}" value="${img}" checked="True"/>
-							</py:when>
-							<py:otherwise>
-								<input type="radio" name="img" id="img:${img}" value="${img}"/>
-							</py:otherwise>
-						</py:choose>
-					</py:when>
-					<py:otherwise>
-						<input type="radio" name="img" id="img:${img}" value="${img}"/>
-					</py:otherwise>
-				</py:choose>
-				<label for="img:${img}"><img src="${ url_for('thumbnail', imgname=img, maxgeometry=100) }" alt="${img}"/></label>
-			</li>
-		</ul>
-		<input type="submit" value="Schild erstellen"/>
-	</form>
+    <py:with vars="messages = get_flashed_messages(with_categories=True)">
+        <ul class="flashes" py:if="messages">
+            <li class="${ category }" py:for="category,message in messages" tabindex="0">${ message }</li>
+        </ul>
+    </py:with>
+    <a href="${ url_for('index') }">Liste der fertigen Schilder</a>
+    
+    <form method="post" action="${ url_for('create') }" enctype="multipart/form-data">
+        <div class="box">
+           <label for="form:template">Wähle eine TeX-Vorlage:</label>
+           <ul>
+                <li py:for="textemplate in templates">
+                    <py:choose>
+                        <py:when test="defined('form')">
+                            <py:choose>
+                                <py:when test="textemplate == form.textemplate">
+                                    <input type="radio" name="textemplate" id="tpl:${textemplate}" value="${textemplate}" checked="True"/>
+                                </py:when>
+                                <py:otherwise>
+                                    <input type="radio" name="textemplate" id="tpl:${textemplate}" value="${textemplate}"/>
+                                </py:otherwise>
+                            </py:choose>
+                        </py:when>
+                        <py:otherwise>
+                            <input type="radio" name="textemplate" id="tpl:${textemplate}" value="${textemplate}"/>
+                        </py:otherwise>
+                    </py:choose>
+                    <label for="tpl:${textemplate}"><img src="${ url_for('tplthumbnail', tplname=textemplate, maxgeometry=72) }" alt="${textemplate}" title="${textemplate}"/></label>
+                </li>
+           </ul>
+        </div><br/>
+        <div class="box">
+            <label for="form:headline">Überschrift</label>
+            <textarea name="headline" id="form:headline" cols="35" rows="5"><py:if test="defined('form')">${form.headline}</py:if></textarea>
+        </div>
+        <div class="box">
+           <label for="form:text">Text</label>
+           <textarea name="text" id="form:text" cols="35" rows="5"><py:if test="defined('form')">${form.text}</py:if></textarea>
+        </div><br/>
+        <div class="box">
+        <input type="submit" value="Schild erstellen"/>
+        </div><br/>
+        <div class="box">
+        <label for="form:img">Wähle ein Bild (falls auf Vorlage anwendbar):</label>
+        <ul>
+            <li>
+                <py:choose>
+                    <py:when test="defined('form')">
+                            <input type="radio" name="img" id="img--none" value="__none" checked="${form.img == '__none'}"/>
+                    </py:when>
+                    <py:otherwise>
+                            <input type="radio" name="img" id="img--none" value="__none" checked="checked" />
+                    </py:otherwise>
+                </py:choose>
+                <label for="img--none">Kein Bild</label>
+            </li>
+            <li>
+                <input type="radio" name="img" id="img--upload" value="__upload"/>
+                <input type="file" name="imgupload"/>
+                <label for="img--upload">Bild hochladen</label>
+            </li>
+        </ul>
+        <ul>
+            <li py:for="img in images">
+                <py:choose>
+                    <py:when test="defined('form')">
+                        <py:choose>
+                            <py:when test="img == form.img">
+                                <input type="radio" name="img" id="img:${img}" value="${img}" checked="True"/>
+                            </py:when>
+                            <py:otherwise>
+                                <input type="radio" name="img" id="img:${img}" value="${img}"/>
+                            </py:otherwise>
+                        </py:choose>
+                    </py:when>
+                    <py:otherwise>
+                        <input type="radio" name="img" id="img:${img}" value="${img}"/>
+                    </py:otherwise>
+                </py:choose>
+                <label for="img:${img}"><img src="${ url_for('thumbnail', imgname=img, maxgeometry=100) }" alt="${img}" title="${img}"/></label>
+            </li>
+        </ul>
+        </div>
+        <div class="box">
+        <input type="submit" value="Schild erstellen"/>
+        </div>
+    </form>
 </body>
 </html>