diff --git a/templates/base.html b/templates/base.html
new file mode 100644
index 0000000..8d039e0
--- /dev/null
+++ b/templates/base.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+ {% block title %}{% endblock %}
+
+
+ {% block style %}{% endblock %}
+
+{% from "navbar.html" import navbar with context %}
+
+
+ {% block nav %}{{ navbar() }}{% endblock %}
+
+ {% if config.SHOW_BLOCK_ALERT %}
+
+ {{ local_block_alert() }}
+ {{ global_block_alert() }}
+
+ {% endif %}
+
+ {% block content %}{% endblock %}
+
+
+
+ {% block script %}{% endblock %}
+
+
diff --git a/templates/navbar.html b/templates/navbar.html
new file mode 100644
index 0000000..789d493
--- /dev/null
+++ b/templates/navbar.html
@@ -0,0 +1,46 @@
+{% macro nav_item(name, label) %}
+
+ {{ label }}{% if name == active %} (current){% endif %}
+
+{% endmacro %}
+
+
+{% macro navbar() %}
+
+{% endmacro %}
diff --git a/templates/show_error.html b/templates/show_error.html
new file mode 100644
index 0000000..e75e75e
--- /dev/null
+++ b/templates/show_error.html
@@ -0,0 +1,30 @@
+{% extends "base.html" %}
+
+{% block style %}
+
+{% endblock %}
+
+{% block content %}
+
+
+
Software error: {{ tb.exception_type }}
+
+
+{% set body %}
+URL: {{ request.url }}
+
+{{ tb.plaintext | safe }}
+{% endset %}
+
+
Submit as an issue on GitHub (requires an account with GitHub)
+
+
Traceback (most recent call last)
+{{ tb.render_summary(include_title=False) | safe }}
+
+
Error in function "{{ last_frame.function_name }}": {{ last_frame_args | pprint }}
+
{{ last_frame.locals | pprint }}
+
+
+{% endblock %}
diff --git a/web_view.py b/web_view.py
index b3e1ec2..727a75f 100755
--- a/web_view.py
+++ b/web_view.py
@@ -1,5 +1,6 @@
#!/usr/bin/python3
+import inspect
import json
import re
from typing import Any, Iterator, TypedDict
@@ -7,7 +8,9 @@ from typing import Any, Iterator, TypedDict
import flask
import lxml.html
import requests
+import werkzeug.exceptions
from requests_oauthlib import OAuth1Session
+from werkzeug.debug.tbtools import get_current_traceback
from werkzeug.wrappers import Response
app = flask.Flask(__name__)
@@ -17,6 +20,22 @@ app.debug = True
api_url = "https://en.wikipedia.org/w/api.php"
+@app.errorhandler(werkzeug.exceptions.InternalServerError)
+def exception_handler(e):
+ tb = get_current_traceback()
+ last_frame = next(frame for frame in reversed(tb.frames) if not frame.is_library)
+ last_frame_args = inspect.getargs(last_frame.code)
+ return (
+ flask.render_template(
+ "show_error.html",
+ tb=tb,
+ last_frame=last_frame,
+ last_frame_args=last_frame_args,
+ ),
+ 500,
+ )
+
+
def get_content(title: str) -> str:
"""Get article text."""
params: dict[str, str | int] = {