--- /dev/null
+#!/usr/bin/env python3
+from bottle import debug, run, default_app, get, view, request, post, redirect
+import os
+import json
+
+web_path = ''
+#web_path = '/guiltcards'
+cards_dir = 'cards/'
+
+def get_card_data(card_id):
+    if not os.path.exists(cards_dir):
+        os.makedirs(cards_dir)
+    path_card = cards_dir + card_id
+    if os.path.exists(path_card):
+        with open(path_card, 'r') as f:
+            data = json.loads(f.read())#f.read()
+    else:
+        data = {'title': '?',
+                'prompt':'?',
+                'answers': ['?', '?']}
+    return data
+
+@get(web_path + '/')
+@view('intro')
+def intro():
+    return dict()
+
+@get(web_path + '/cards')
+@view('cards')
+def list_cards():
+    if not os.path.exists(cards_dir):
+        os.makedirs(cards_dir)
+    card_ids = os.listdir(cards_dir)
+    return dict(web_path=web_path,
+                card_ids=card_ids)
+
+@get(web_path + '/cards/')
+def new_card():
+    card_id = request.query.get('card_id')
+    redirect(web_path + '/cards/' + card_id + '/form')
+
+@get(web_path + '/cards/<card_id>/view')
+@view('card')
+def show_card(card_id):
+    data = get_card_data(card_id)
+    return dict(web_path=web_path,
+                title=data['title'],
+                prompt=data['prompt'],
+                answers=data['answers'])
+
+@post(web_path + '/cards/<card_id>')
+def update_card(card_id):
+    if not os.path.exists(cards_dir):
+        os.makedirs(cards_dir)
+    path_card = cards_dir + card_id
+    json_dict = {
+        'title': request.forms.get('title'),
+        'prompt': request.forms.get('prompt'),
+        'answers': request.forms.getall('answer')
+    }
+    json_dict['answers'] = [answer for answer in json_dict['answers']
+                            if answer.strip() != '']
+    with open(path_card, 'w') as f:
+        f.write(json.dumps(json_dict, indent=4))
+    redirect(web_path + '/cards/' + card_id + '/view')
+
+@get(web_path + '/cards/<card_id>/form')
+@view('card_form')
+def card_form(card_id):
+    data = get_card_data(card_id)
+    card_path = cards_dir + '/' + card_id
+    deletable = False
+    if os.path.exists(card_path):
+        deletable = True
+    return dict(web_path=web_path,
+                card_id=card_id,
+                title=data['title'],
+                prompt=data['prompt'],
+                answers=data['answers'],
+                deletable=deletable)
+
+@get(web_path + '/cards/<card_id>/delete')
+@view('delete_card')
+def delete_card_ask(card_id):
+    return dict(web_path=web_path,
+                card_id=card_id)
+
+@post(web_path + '/cards/<card_id>/delete')
+def delete_card_do(card_id):
+    card_path = cards_dir + '/' + card_id
+    if os.path.exists(card_path):
+        os.remove(card_path)
+    redirect(web_path + '/cards')
+
+# App running.
+
+if __name__ == "__main__":
+    debug(True)
+    run(port=8000)
+else:
+    app = application = default_app()
 
--- /dev/null
+<!DOCTYPE HTML>
+<html>
+<body>
+<form action="{{ web_path }}/cards/{{ card_id }}" method="POST">
+title: <input type="text" name="title" value="{{ title }}" /><br />
+prompt: <input type="text" name="prompt" value="{{ prompt }}" /><br />
+% for answer in answers:
+answer: <input type="text" name="answer" value="{{ answer }}" /><br />
+% end
+answer: <input type="text" name="answer" /><br />
+answer: <input type="text" name="answer" /><br />
+answer: <input type="text" name="answer" /><br />
+<input type="submit" value="OK" />
+</form>
+<p>
+(leave specific answer fields empty to remove them as answer options)
+</p>
+% if deletable:
+<p>
+Or would you rather <a href="{{ web_path }}/cards/{{ card_id }}/delete">DELETE</a> this card?
+</p>
+% end
+</form>
+</body>
+</html>