]> OzVa Git service - chester/commitdiff
rebuild for CRJ
authorMax Value <greenwoodw50@gmail.com>
Tue, 2 Dec 2025 17:31:06 +0000 (17:31 +0000)
committerMax Value <greenwoodw50@gmail.com>
Tue, 2 Dec 2025 17:31:06 +0000 (17:31 +0000)
120 files changed:
Makefile
site/__pycache__/categories.cpython-313.pyc [new file with mode: 0644]
site/__pycache__/media.cpython-313.pyc [new file with mode: 0644]
site/__pycache__/page.cpython-313.pyc [new file with mode: 0644]
site/__pycache__/search.cpython-313.pyc [new file with mode: 0644]
site/__pycache__/utils.cpython-313.pyc [new file with mode: 0644]
site/blog.py [deleted file]
site/main.py [new file with mode: 0755]
site/src/bayeux.md [new file with mode: 0644]
site/src/bayeux1.png [new file with mode: 0644]
site/src/beat.md
site/src/bread.md [new file with mode: 0644]
site/src/champagne.md [new file with mode: 0644]
site/src/example.md [new file with mode: 0644]
site/src/homepage.md [new file with mode: 0644]
site/src/loaf.md [new file with mode: 0644]
site/src/niceones.md [new file with mode: 0644]
site/src/plotter.md [new file with mode: 0644]
site/src/porn.md [new file with mode: 0644]
site/src/smoked.md [new file with mode: 0644]
site/src/stft.md [new file with mode: 0644]
site/src/weber.md [new file with mode: 0644]
site/static/favicon.ico [new file with mode: 0644]
site/static/font.css [new file with mode: 0644]
site/static/fonts/Literata-Black.eot [deleted file]
site/static/fonts/Literata-Black.ttf [deleted file]
site/static/fonts/Literata-Black.woff [deleted file]
site/static/fonts/Literata-Black.woff2 [deleted file]
site/static/fonts/Literata-BlackItalic.eot [deleted file]
site/static/fonts/Literata-BlackItalic.ttf [deleted file]
site/static/fonts/Literata-BlackItalic.woff [deleted file]
site/static/fonts/Literata-BlackItalic.woff2 [deleted file]
site/static/fonts/Literata-Bold.eot [deleted file]
site/static/fonts/Literata-Bold.ttf [deleted file]
site/static/fonts/Literata-Bold.woff [deleted file]
site/static/fonts/Literata-Bold.woff2 [deleted file]
site/static/fonts/Literata-BoldItalic.eot [deleted file]
site/static/fonts/Literata-BoldItalic.ttf [deleted file]
site/static/fonts/Literata-BoldItalic.woff [deleted file]
site/static/fonts/Literata-BoldItalic.woff2 [deleted file]
site/static/fonts/Literata-ExtraBold.eot [deleted file]
site/static/fonts/Literata-ExtraBold.ttf [deleted file]
site/static/fonts/Literata-ExtraBold.woff [deleted file]
site/static/fonts/Literata-ExtraBold.woff2 [deleted file]
site/static/fonts/Literata-ExtraBoldItalic.eot [deleted file]
site/static/fonts/Literata-ExtraBoldItalic.ttf [deleted file]
site/static/fonts/Literata-ExtraBoldItalic.woff [deleted file]
site/static/fonts/Literata-ExtraBoldItalic.woff2 [deleted file]
site/static/fonts/Literata-ExtraLight.eot [deleted file]
site/static/fonts/Literata-ExtraLight.ttf [deleted file]
site/static/fonts/Literata-ExtraLight.woff [deleted file]
site/static/fonts/Literata-ExtraLight.woff2 [deleted file]
site/static/fonts/Literata-ExtraLightItalic.eot [deleted file]
site/static/fonts/Literata-ExtraLightItalic.ttf [deleted file]
site/static/fonts/Literata-ExtraLightItalic.woff [deleted file]
site/static/fonts/Literata-ExtraLightItalic.woff2 [deleted file]
site/static/fonts/Literata-Italic.eot [deleted file]
site/static/fonts/Literata-Italic.ttf [deleted file]
site/static/fonts/Literata-Italic.woff [deleted file]
site/static/fonts/Literata-Italic.woff2 [deleted file]
site/static/fonts/Literata-Light.eot [deleted file]
site/static/fonts/Literata-Light.ttf [deleted file]
site/static/fonts/Literata-Light.woff [deleted file]
site/static/fonts/Literata-Light.woff2 [deleted file]
site/static/fonts/Literata-LightItalic.eot [deleted file]
site/static/fonts/Literata-LightItalic.ttf [deleted file]
site/static/fonts/Literata-LightItalic.woff [deleted file]
site/static/fonts/Literata-LightItalic.woff2 [deleted file]
site/static/fonts/Literata-Medium.eot [deleted file]
site/static/fonts/Literata-Medium.ttf [deleted file]
site/static/fonts/Literata-Medium.woff [deleted file]
site/static/fonts/Literata-Medium.woff2 [deleted file]
site/static/fonts/Literata-MediumItalic.eot [deleted file]
site/static/fonts/Literata-MediumItalic.ttf [deleted file]
site/static/fonts/Literata-MediumItalic.woff [deleted file]
site/static/fonts/Literata-MediumItalic.woff2 [deleted file]
site/static/fonts/Literata-Regular.eot [deleted file]
site/static/fonts/Literata-Regular.ttf [deleted file]
site/static/fonts/Literata-Regular.woff [deleted file]
site/static/fonts/Literata-Regular.woff2 [deleted file]
site/static/fonts/Literata-SemiBold.eot [deleted file]
site/static/fonts/Literata-SemiBold.ttf [deleted file]
site/static/fonts/Literata-SemiBold.woff [deleted file]
site/static/fonts/Literata-SemiBold.woff2 [deleted file]
site/static/fonts/Literata-SemiBoldItalic.eot [deleted file]
site/static/fonts/Literata-SemiBoldItalic.ttf [deleted file]
site/static/fonts/Literata-SemiBoldItalic.woff [deleted file]
site/static/fonts/Literata-SemiBoldItalic.woff2 [deleted file]
site/static/fonts/Literata-Variable.eot [deleted file]
site/static/fonts/Literata-Variable.ttf [deleted file]
site/static/fonts/Literata-Variable.woff [deleted file]
site/static/fonts/Literata-Variable.woff2 [deleted file]
site/static/fonts/Literata-VariableItalic.eot [deleted file]
site/static/fonts/Literata-VariableItalic.ttf [deleted file]
site/static/fonts/Literata-VariableItalic.woff [deleted file]
site/static/fonts/Literata-VariableItalic.woff2 [deleted file]
site/static/fonts/WorkSans-Black.ttf [new file with mode: 0644]
site/static/fonts/WorkSans-BlackItalic.ttf [new file with mode: 0644]
site/static/fonts/WorkSans-Bold.ttf [new file with mode: 0644]
site/static/fonts/WorkSans-BoldItalic.ttf [new file with mode: 0644]
site/static/fonts/WorkSans-ExtraBold.ttf [new file with mode: 0644]
site/static/fonts/WorkSans-ExtraBoldItalic.ttf [new file with mode: 0644]
site/static/fonts/WorkSans-ExtraLight.ttf [new file with mode: 0644]
site/static/fonts/WorkSans-ExtraLightItalic.ttf [new file with mode: 0644]
site/static/fonts/WorkSans-Italic.ttf [new file with mode: 0644]
site/static/fonts/WorkSans-Light.ttf [new file with mode: 0644]
site/static/fonts/WorkSans-LightItalic.ttf [new file with mode: 0644]
site/static/fonts/WorkSans-Medium.ttf [new file with mode: 0644]
site/static/fonts/WorkSans-MediumItalic.ttf [new file with mode: 0644]
site/static/fonts/WorkSans-Regular.ttf [new file with mode: 0644]
site/static/fonts/WorkSans-SemiBold.ttf [new file with mode: 0644]
site/static/fonts/WorkSans-SemiBoldItalic.ttf [new file with mode: 0644]
site/static/fonts/WorkSans-Thin.ttf [new file with mode: 0644]
site/static/fonts/WorkSans-ThinItalic.ttf [new file with mode: 0644]
site/static/literata.css [deleted file]
site/static/query.css [new file with mode: 0644]
site/static/script.js
site/static/style.css
site/templates/homepage.md [deleted file]
site/templates/page.html

index 5ac3925e72d3b4f4eb0c87fbfad06e0003f93e13..565ee29834bd283ebd6eab2d6127767003c9cb3d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,8 @@
 all : .venv/touchfile
 
+test : .venv/touchfile
+       .venv/bin/python site/main.py
+
 .venv/touchfile : requirements.txt
        python3 -m venv .venv
        .venv/bin/pip install -r requirements.txt
diff --git a/site/__pycache__/categories.cpython-313.pyc b/site/__pycache__/categories.cpython-313.pyc
new file mode 100644 (file)
index 0000000..e5f5524
Binary files /dev/null and b/site/__pycache__/categories.cpython-313.pyc differ
diff --git a/site/__pycache__/media.cpython-313.pyc b/site/__pycache__/media.cpython-313.pyc
new file mode 100644 (file)
index 0000000..a8ecbca
Binary files /dev/null and b/site/__pycache__/media.cpython-313.pyc differ
diff --git a/site/__pycache__/page.cpython-313.pyc b/site/__pycache__/page.cpython-313.pyc
new file mode 100644 (file)
index 0000000..531beba
Binary files /dev/null and b/site/__pycache__/page.cpython-313.pyc differ
diff --git a/site/__pycache__/search.cpython-313.pyc b/site/__pycache__/search.cpython-313.pyc
new file mode 100644 (file)
index 0000000..df4e86f
Binary files /dev/null and b/site/__pycache__/search.cpython-313.pyc differ
diff --git a/site/__pycache__/utils.cpython-313.pyc b/site/__pycache__/utils.cpython-313.pyc
new file mode 100644 (file)
index 0000000..134e04e
Binary files /dev/null and b/site/__pycache__/utils.cpython-313.pyc differ
diff --git a/site/blog.py b/site/blog.py
deleted file mode 100755 (executable)
index 1f35152..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-#! .venv/bin/python3
-
-from flask import Flask, Response, request, render_template_string, redirect, send_from_directory
-import markdown
-from os import listdir, environ
-from os.path import getmtime
-from markdown.extensions.toc import TocExtension
-import re
-import time
-
-app = Flask(__name__)
-md = markdown.Markdown(extensions = ['meta', 'tables', 'footnotes', TocExtension(title = "Table of contents")])
-
-blog_path = environ["BLOG_PATH"]
-
-repo = Repo.init(blog_path)
-
-class Page():
-       def __init__(
-               self,
-               title: str = "Unamed page",
-               abstract: str = "",
-               keywords: list = ["Undefined"],
-               date: str = "n.d.",
-               content: str = "",
-               template: str = "page.html",
-               filename: str = ""
-               ):
-
-               self.title = title
-               self.abstract = abstract
-               self.keywords = keywords
-               self.date = date
-               self.content = content
-               self.template = template
-               self.filename = filename
-
-       def from_metadata(self, metadata):
-               if "title" in metadata: self.title = metadata["title"].title()
-               if "abstract" in metadata: self.abstract = metadata["abstract"]
-               if "keywords" in metadata: self.keywords = [x.strip().title() for x in metadata["keywords"].split(",")]
-               if "date" in metadata: self.date = metadata["date"]
-
-       def make(self):
-               format_keywords = " - ".join([f"<a href='/categories?name={key.lower()}'>{key}</a>" for key in self.keywords])
-
-               template_string = open(f"{blog_path}/templates/{self.template}", "r").read()
-
-               with open(f"{blog_path}/templates/sidebar.md", "r") as f:
-                       sidebar = md.convert(f.read())
-
-               page = render_template_string(
-                       template_string,
-                       title = self.title,
-                       date = self.date,
-                       abstract = self.abstract,
-                       keywords = format_keywords,
-                       content = self.content,
-                       filename = self.filename,
-                       sidebar = sidebar
-                       )
-
-               return Response(page, mimetype="text/html")
-
-def get_plaintext(file_name: str):
-       page = open(f"{blog_path}/pages/{file_name}", "r").read()
-       return re.sub(
-               r"((?<![\S ])\w*:[\S\t ]*)|((?<=\n)##* )|(\n![\S ]*(?=\n))|(\[\^\d*\])|([\S ]*\<[\S ]*\>[\S ]*)|(``*)",
-               "",
-               page)
-
-def get_metadata(file_name: str):
-       title = "Untitled post"
-       abstract = "..."
-       keywords = ["Undefined"]
-
-       with open(f"{blog_path}/pages/{file_name}", "r") as f:
-               while keywords == ["Undefined"]:
-                       line = f.readline().split(":") # Split metdata into [key, value]
-                       if len(line) == 2: # len != 2 when metadata block is over
-                               key,  value = line
-                               match key:
-                                       case "title":
-                                               title = value.strip().title()
-                                       case "abstract":
-                                               abstract = value.strip()
-                                       case "keywords":
-                                               keywords = [x.strip() for x in value.split(",")]
-                       else:
-                               break
-
-       return title, abstract, keywords
-
-def get_recent(n):
-       modification_times = {file_name: getmtime(f"{blog_path}/pages/{file_name}") for file_name in listdir(f"{blog_path}/pages")}
-       pages = sorted(modification_times.items(), key=lambda x: x[1])[:n]
-
-       content = "<h3>Recent Posts</h3><ul>"
-
-       for page in pages:
-               title, abstract, keywords = get_metadata(page[0])
-               content += f"""
-                       <li>
-                               <a href='/{page[0][:-3]}'><b>{title}</b></a>
-                       </li>
-               """
-
-       content += "</ul>"
-
-       return content
-
-@app.route("/")
-def homepage():
-       with open(f"{blog_path}/templates/homepage.md", "r") as f:
-               homepage = md.convert(f.read())
-
-       page = Page(
-               title = "Home",
-               abstract = "Blog and portfolio of Will Greenwood.",
-               keywords = [],
-               date = "",
-               content = homepage + get_recent(10),
-               template = "page.html"
-               )
-       return page.make()
-
-@app.route("/search")
-def get_search():
-       search = request.args.get("name")
-
-       results = 0
-       content = f"<h1>Search '<em>{search}</em>'</h1><ul>"
-
-       if search != "":
-               for file_name in listdir(f"{blog_path}/pages"):
-                       page = get_plaintext(file_name)
-                       i = page.casefold().find(search.casefold())
-
-                       if i != -1:
-                               results += 1
-                               content += f"""
-                                       <li>
-                                               <a href='/{file_name[:-3]}'>
-                                                       {get_metadata(file_name)[0]}
-                                               </a> - <em>
-                                                       '...
-                                                       <b>{page[i:i+len(search)]}</b>
-                                                       {page[i+len(search):i+50]}
-                                                       ...'
-                                               </em>
-                                       </li>"""
-
-       if results == 0:
-               content += "</ul><p>No results found</p>"
-       else:
-               content += f"</ul><p>{results} results found</p>"
-
-       page = Page(
-               title = "Post search",
-               date = "",
-               keywords = [],
-               content = content
-               )
-       return page.make()
-
-@app.route("/categories")
-def get_categories():
-       name = request.args.get("name")
-       index = {}
-
-       if name == "all":
-               return redirect("/categories")
-
-       for file_name in listdir(f"{blog_path}/pages"):
-               title, abstract, keywords = get_metadata(file_name)
-
-               entry = {"title": title, "abstract": abstract,  "path": f"/{file_name[:-3]}"}
-               for key in keywords:
-                       if key in index:
-                               index[key] += [entry]
-
-                       elif name is None:
-                               index.update({key: [entry]})
-
-                       elif key.lower() == name.lower():
-                               index.update({key: [entry]})
-
-       content = ""
-       for c in index:
-               content += f"<h1>{c.title()}</h1><ul>"
-
-               for post in index[c]:
-                       content += f"<li><a href='{post['path']}'>{post['title']}</a> - <em>{post['abstract']}</em></li>"
-
-               content += "</ul>"
-
-       page = Page(
-               title = "Keyword search",
-               abstract = "Click on a keyword to see all pages tagged with that keyword.",
-               date = "",
-               keywords = [c.title() for c in index] + ["All"],
-               content = content
-               )
-       return page.make()
-
-@app.route("/<string:title>")
-def generate_page(title):
-       title = title.replace("/", "")
-       try:
-               with open(f"{blog_path}/pages/{title}.md", "r") as f:
-                       html = md.convert(f.read())
-                       metadata = {k: v[0] for k, v in md.Meta.items()}
-                       md.reset()
-
-               page = Page(content = html, filename = title)
-               page.from_metadata(metadata)
-               return page.make()
-
-       except FileNotFoundError:
-               page = Page(title = "404", abstract = "Page not found!")
-               return page.make()
-
-@app.route("/<string:title>/<string:filename>")
-def get_media(title, filename):
-       return send_from_directory(f"{blog_path}/media/{title}", filename)
-
-if __name__ == "__main__":
-       app.run(host='127.0.0.1', port=5000, debug=True)
diff --git a/site/main.py b/site/main.py
new file mode 100755 (executable)
index 0000000..2db81ec
--- /dev/null
@@ -0,0 +1,200 @@
+#! .venv/bin/python3
+
+from flask import Flask, Response, request, render_template_string, redirect, send_file
+import markdown
+from os import listdir, environ
+from os.path import getmtime, basename
+from markdown.extensions.toc import TocExtension
+import glob
+import re
+import time
+
+app = Flask(__name__)
+md = markdown.Markdown(extensions = ['meta', 'footnotes', TocExtension(title = "Table of contents")])
+
+class Page():
+       def __init__(
+               self,
+               title: str = "Unamed page",
+               keywords: list = ["Undefined"],
+               date: str = "n.d.",
+               content: str = "",
+               filename: str = ""
+               ):
+
+               self.title = title
+               self.keywords = keywords
+               self.date = date
+               self.content = content
+               self.filename = filename
+
+       def from_metadata(self, metadata):
+               if "title" in metadata: self.title = metadata["title"].title()
+               if "keywords" in metadata: self.keywords = [x.strip().title() for x in metadata["keywords"].split(",")]
+               if "date" in metadata: self.date = metadata["date"]
+
+       def make(self):
+               format_keywords = " - ".join([f"<a href='#tag-{key.lower()}'>{key}</a>" for key in self.keywords])
+
+               template_string = open(f"{app.root_path}/templates/page.html", "r").read()
+
+               page = render_template_string(
+                       template_string,
+                       title = self.title,
+                       date = self.date,
+                       keywords = format_keywords,
+                       content = self.content,
+                       filename = self.filename,
+                       sidebar = get_categories()
+                       )
+
+               return Response(page, mimetype="text/html")
+
+def get_files():
+       data = glob.glob(f"{app.root_path}/src/**/*", recursive=True)
+
+       data = {
+               basename(x): x
+               for x in data
+               }
+
+       return data
+
+def get_plaintext(file_name: str):
+       page = open(get_files()[file_name], "r").read()
+       return re.sub(
+               r"((?<![\S ])\w*:[\S\t ]*)|((?<=\n)##* )|(\n![\S ]*(?=\n))|(\[\^\d*\])|([\S ]*\<[\S ]*\>[\S ]*)|(``*)",
+               "",
+               page)
+
+def get_metadata(file_name: str):
+       title = "Untitled post"
+       keywords = ["Undefined"]
+
+       with open(get_files()[file_name], "r") as f:
+               while keywords == ["Undefined"]:
+                       line = f.readline().split(":") # Split metdata into [key, value]
+                       if len(line) == 2: # len != 2 when metadata block is over
+                               key,  value = line
+                               match key:
+                                       case "title":
+                                               title = value.strip().title()
+                                       case "keywords":
+                                               keywords = [x.strip() for x in value.split(",")]
+                       else:
+                               break
+
+       return title, keywords
+
+@app.route("/")
+def homepage():
+       with open(f"{app.root_path}/src/homepage.md", "r") as f:
+               homepage = md.convert(f.read())
+
+       page = Page(
+               title = "Home",
+               keywords = [],
+               date = "",
+               content = homepage,
+               )
+       return page.make()
+
+@app.route("/search")
+def get_search():
+       search = request.args.get("name")
+
+       results = 0
+       content = f"<h1>'<em>{search}</em>'</h1><ul>"
+
+       if search != "":
+               for file_name in get_files():
+                       if file_name[-3:] != ".md": continue
+                       page = get_plaintext(file_name)
+                       i = page.casefold().find(search.casefold())
+
+                       if i != -1:
+                               results += 1
+                               content += f"""
+                                       <li>
+                                               <a href='/{file_name[:-3]}'>
+                                                       {get_metadata(file_name)[0]}
+                                               </a> - <em>
+                                                       '...
+                                                       <b>{page[i:i+len(search)]}</b>
+                                                       {page[i+len(search):i+50]}
+                                                       ...'
+                                               </em>
+                                       </li>"""
+
+       if results == 0:
+               content += "</ul><p>No results found</p>"
+       else:
+               content += f"</ul><p>{results} results found</p>"
+
+       page = Page(
+               title = "Search",
+               date = "",
+               keywords = [],
+               content = content
+               )
+       return page.make()
+
+def get_categories():
+       name = request.args.get("name")
+       index = {}
+
+       for file_name in get_files():
+               if file_name[-3:] != ".md": continue
+               elif file_name == "homepage.md": continue
+               elif file_name == "example.md": continue
+               title, keywords = get_metadata(file_name)
+
+               entry = {"title": title,  "path": f"/{file_name[:-3]}"}
+               for key in keywords:
+                       if key in index:
+                               index[key] += [entry]
+
+                       elif name is None:
+                               index.update({key: [entry]})
+
+                       elif key.lower() == name.lower():
+                               index.update({key: [entry]})
+
+       content = ""
+       for c in index:
+               content += f"<details><summary>{c.title()}</summary><ul id='tag-{c}'>"
+
+               for post in index[c]:
+                       content += f"<li><a href='{post['path']}'>{post['title']}</a></li>"
+
+               content += "</ul></details>"
+
+       return content
+
+@app.route("/<string:title>")
+def generate_page(title):
+       if "." in title:
+               path = get_files()[title]
+               return send_file(path)
+
+       title = title.replace("/", "")
+       try:
+               with open(get_files()[f"{title}.md"], "r") as f:
+                       html = md.convert(f.read())
+                       metadata = {k: v[0] for k, v in md.Meta.items()}
+                       md.reset()
+
+               page = Page(content = html, filename = title)
+               page.from_metadata(metadata)
+               return page.make()
+
+       except FileNotFoundError:
+               page = Page(title = "404")
+               return page.make()
+
+@app.route("/<string:title>/<string:filename>")
+def get_media(title, filename):
+       return send_from_directory(f"{app.root_path}/media/{title}", filename)
+
+if __name__ == "__main__":
+       app.run(host='127.0.0.1', port=5000, debug=True)
diff --git a/site/src/bayeux.md b/site/src/bayeux.md
new file mode 100644 (file)
index 0000000..d775ae1
--- /dev/null
@@ -0,0 +1,72 @@
+title: An Audio Bayeux Tapestry
+keywords: programming,audio
+date: 16/12/2024
+
+# An Audio Bayeux Tapestry
+
+Hello!
+
+With the power of technology, the Bayeux tapestry is now avaiable for the blind.
+
+<audio src="https://blog.ozva.co.uk/bayeux/bayeux.mp3" controls />
+
+In this post I'll show you how this was achived.
+
+## The image
+
+![image](bayeux1.png "Before ajustment")
+
+The scan available online[^1] is not centered, unless we want an unclear or ragged edge on our audio, we must first straighten and strectch the tapestry flat.
+
+I did this with a simple python script.
+
+```
+for (i, pixel) in enumerate(line):
+    value = np.mean(pixel) # Get the brightness
+    if value < THRESHHOLD:
+        front_index = i # Set the index of our in-point
+        break
+```
+
+As you can see, by scrolling our way across each line and noting where the pixel value is greater than our threshold (set at 225), we can figure out the bounds of that particular line of the tapestry.
+
+```
+trim_line = np.array([line[front_index:back_index]], dtype=np.uint8)
+new_image.append(cv.resize(trim_line, (image_width, 1))[0])
+```
+
+We then stretch the line to the total width of the image.
+
+This produces a far more regular image.
+
+![image](/bayeux/bayeux2.png "After ajustment")
+
+This is very stretched, but this is no problem. Since it will end up as a spectrogram whose dimentions we don't care much for we will skip the step of fixing this.
+
+## The spectrogram
+
+The image can then be turned into a spectrogram with the power of the FFT.
+
+```
+data = np.fft.irfft(image, h*2, axis=1).reshape((w*h*2)) # Reshape and get the FFT output
+data -= np.average(data) # Remove DC offset
+data *= (2**15-1.)/np.amax(data) # Normalize
+```
+
+As a side effect of the jump from one side of the image to the other, there is a sample impulse every 1,500 samples, we record this high point and subtract it from all following samples.
+
+```
+high_point = data[1500]
+for i in range(0, len(data), 1500):
+    data[i] -= high_point
+```
+
+If we split the image in half and process seperately, we can then combine them over the right and left audio channels to get a more resolute image.
+
+This solves another issue:
+
+Say you have an image which is not so rectangular and is intended to have a "silent" background. As this image rises to the top of the frame, hovering around 20,000kHz it can become quite unplesant. Splitting the sound across right and left not only produces some sence of space, but also gives you a wholy wider and more plesent range of frequencies.
+
+![image](/bayeux/bayeux3.png "Finished spectrogram")
+
+[^1]: Link: <https://en.wikipedia.org/wiki/File:Tapisserie_de_Bayeux_31109.jpg>
diff --git a/site/src/bayeux1.png b/site/src/bayeux1.png
new file mode 100644 (file)
index 0000000..64898fc
Binary files /dev/null and b/site/src/bayeux1.png differ
index ccda813c6553efdab713195fdb709b27a45288a7..9aa880cf1fd25a6115efa761056f60d4f4128079 100644 (file)
@@ -1,5 +1,4 @@
 title: An XMDV Poem
-abstract: Exquisite corpse poem by myself and my wonderful narrative director.
 keywords: art
 date: 17/05/2025
 
diff --git a/site/src/bread.md b/site/src/bread.md
new file mode 100644 (file)
index 0000000..32b4377
--- /dev/null
@@ -0,0 +1,9 @@
+title: Bread
+keywords: bread
+date: 17/05/2025
+
+![image](/bread/banner.png "Bread book spine")
+
+# See <https://bread.ozva.co.uk>
+
+
diff --git a/site/src/champagne.md b/site/src/champagne.md
new file mode 100644 (file)
index 0000000..e221c9d
--- /dev/null
@@ -0,0 +1,29 @@
+title: A bottle to smash on the hull of my boat
+keywords: programming,meta
+date: 29/10/2024
+
+Last year I decided to setup a small blog. Knowing full well that I could build my own, but also that it would be a huge time-sink that I really didnt have the time for, I decided to simply use Blogspot. It's surpisingly good and uses rich-text levels of formatting to produce slightly disapointing looking pages. My usual lean towards minimalism and accessibility was completely undermined by the control I had over how the blog looked. So it has sinc upset me, as somone so keen on self-hosting, that my blog (and emails) is managed by Google.
+
+# One year on and It's been a huge time-sink.
+
+Well about a week. But it's more difficult now. I'm at that sweet spot in learning a skill where i'm just good enough to basically make whatever I might want, but I still mess up enough to keep it interesting. It makes such a strong pull I have been able to think about very little that *isn't* dynamic page generation.
+
+I am, yet again, going with minimalism, combined with the nomenclature of acedemic writing.
+
+This is mirrored in both the approach i've taken to the various important desisions when building the generator, as well as words and styling of the pages. For example, the title / abstract / keywords / content structure, whether accurate to acedemia or not, reflects some kind of constant confort-structure. Not only this but it serves, as in acedemia, to give the reader some taste of the body of text before the continue. Combined with keywords and a future search system, this provides both this confort-structure and a robust way of narrowing down your reading. These features are handeled when generating every page, and although it is possible to exclude the date when not neccicary (such as the keyword search page), this must be done consiously and manually.
+
+This kind of structure (written out by hand, by me, every time) ensures that each page is sorted and labeled properly in a way that Blogger made barely dooable and also unplesant.
+
+2 semi-structural elements also included is the table of contents (TOC) and footnotes. Although the TOC could be programatically included within the generator, I made the desision to require it to be consiously included within the page. This not only adds weight to larger pages, requiring a TOC, but also allows page-by-page desision on where that TOC should be placed.
+
+I've also chosen to move away from any concept of time. With gaps between posts unpredictable, I would rather it not be immediately obvious that I did 2 posts a day for a month and then stopped for 5. Not that date-of-writing will not be open information, but it will not be sorted by the metric, and will not be ranked anywhere by most recent.
+
+I would describe this approach as:
+
+# Just enough.
+
+There are just enough features, and if I really need anything else, it can be added. If search proves too difficult, or breaks with the approach, it can be left out. Sites are simple HTML, with few stylings, all preloaded on hover for speed. And the "just enough" amount of marking-down for this minimalist writing is markdown. Future-proof should I ever choose to migrate again, lightweight should I keep writing and it can even do tables! The code for the generator is open-source and can be see at the repo. Over the next few weeks, I will atempt to migrate the old blog over to this system.
+
+Thanks,
+
+Will
diff --git a/site/src/example.md b/site/src/example.md
new file mode 100644 (file)
index 0000000..8396fe3
--- /dev/null
@@ -0,0 +1,57 @@
+title: An Audio Bayeux Tapestry
+keywords: programming,audio
+date: 16/12/2024
+
+Oh by the way you can do a table of contents. Could be good for something longer?
+
+[TOC]
+
+## This is a Heading
+
+### This is another
+
+With the power of technology, the Bayeux tapestry is now avaiable for the blind.
+
+Theres a whole line in-between each different peice.
+
+## An Image
+
+![image](bayeux1.png "Before ajustment")
+
+The scan available online[^1] is not centered, unless we want an unclear or ragged edge on our audio, we must first straighten and strectch the tapestry flat.
+
+See that thing above? It's a footnote! They dont need to be in numerical order.
+
+Oh i dont think you'll use it but code blocks are 3 backticks. These also work well for sections you dont want formatted propperly, poems maybe?
+
+```
+for (i, pixel) in enumerate(line):
+    value = np.mean(pixel) # Get the brightness
+    if value < THRESHHOLD:
+        front_index = i # Set the index of our in-point
+        break
+```
+
+![image](/bayeux/bayeux2.png "After ajustment")
+
+The little "After ajustment" is the little note that pops up when you hover over the image
+
+This is very stretched, but this is no problem. Since it will end up as a spectrogram whose dimentions we don't care much for we will skip the step of fixing this.
+
+Before we do another part lets do a horizontal line:
+
+---
+
+## The spectrogram
+
+The image can then be turned into a spectrogram with the power of the FFT.
+
+As a side effect of the jump from one side of the image to the other, there is a sample impulse every 1,500 samples, we record this high point and subtract it from all following samples.
+
+If we split the image in half and process seperately, we can then combine them over the right and left audio channels to get a more resolute image.
+
+This solves another issue:
+
+Say you have an image which is not so rectangular and is intended to have a "silent" background. As this image rises to the top of the frame, hovering around 20,000kHz it can become quite unplesant. Splitting the sound across right and left not only produces some sence of space, but also gives you a wholy wider and more plesent range of frequencies.
+
+[^1]: Link: <https://en.wikipedia.org/wiki/File:Tapisserie_de_Bayeux_31109.jpg>
diff --git a/site/src/homepage.md b/site/src/homepage.md
new file mode 100644 (file)
index 0000000..c32c834
--- /dev/null
@@ -0,0 +1,7 @@
+
+
+# Hello this is the homepage
+
+Test Test Test!
+
+Well done everyone
diff --git a/site/src/loaf.md b/site/src/loaf.md
new file mode 100644 (file)
index 0000000..6df404e
--- /dev/null
@@ -0,0 +1,142 @@
+title: A new National-Loaf
+keywords: bread
+date: 16/12/2024
+
+This project is tracked via git, repo can be found here: <https://git.ozva.co.uk/?p=national-loaf;a=summary>
+
+[TOC]
+
+# Disclaimer
+
+I will not be discussing the general operations of a group of people unless they are expressly related to bread. Individual survival and operations of your community is up to you. I will also not be discussing growing wheat or other crops, it is something I know little about. Although this would be necessary to maintain the bakery indefinitely, both are outside of the scope of this essay.
+
+# Ingredients
+
+The first thing you will want to do after securing a property, is procure supplies and equipment. If cars and vans are not available, use wheelbarrows.
+
+Care must be taken to keep all supplies in a sustainable location. Keeping moisture away from flour and salt, as well as generally, is best. Try to pick a high up location or a building unlikely to suffer from flooding or rodent infestation.
+
+## Flour
+
+Flour is by far the most important ingredient in bread, as well as the most difficult one to acquire. As mentioned, growing and processing crops would be an ideal end goal, but it is unfortunately outside of the scope of this essay. Therefore we will be assuming access to at least some form of cereal crop at the very least, and processed flour at the very most.
+
+Cereal crops like wheat, rice, barley and oats, all grow with an innedible shell surrounding them, called the chaff.
+
+Assuming some raw crop, the grian kernal must first be seperated from the chaff. This was done traditionally by tossing the grains into the air, letting the heavier kernals fall to be collected, and the lighter chaff get blown away in the wind. should this not be effective, the grain can be pounded or soaked to loosen the chaff. This can be done easily by anyone, and scales moderately well with woven baskets. Baskets can additionally be used to sift the grain to remove the chaff.
+
+The grain kernel is then ready to be milled down into flour. This was done traditionally with two large stones with groves cut into them, the grains fed in through the top. It is done now with a collection of motorized metal rolers which crush the grain.
+
+Millstones where traditionally made from grainite, which can be acquired from any nearby tile shop, a thick piece of granite with some grooves cut in it will work perfectly. Grooves can be cut with an angle grinder, or chisled by hand. 
+
+For us, milling would be possible, but hard work if done manually. It could potentially be hooked up to some form of motor, as it would only be running intermittently, or even mechanically coupled to to a water wheel or wind turbine.
+
+If we assume processed flour is available, this becomes far easier.
+
+1.5kg, 5kg and 10kg bags of flour are stocked in most large supermarkets, as well as Asian supermarkets, as large bags of chapatti flour. You would initially want to sweep the local area to collect as much as possible. Takeaways and wholesale food suppliers will most likely stock large amounts of some kind of flour. Most homes, also, keep a bag or two of flour and a bag could be swapped in return for the equivalent of bread.
+
+Takeaway shops would also be a good source of flour, and would be helpful in plenty of ways. Any takeaway, or any restaurent, selling battered food will keep a large 25kg bag of batter, which consists mostly of flour.
+
+Any cereal grain you can get your hands on will be of use, whether it be added whole or milled down, and almost any powdered grain can be added to bread to some effect. Being, by name, cereal, they will be under high demand. Think carefully about what you use. Grain can be used in many ways, and although you are a bakery, your end goal is to feed the people, not to make as much bread as possible. Do not do bad things to make good bread. Take what is surplus and make good bread.
+
+## Water
+
+Good water from a natural source is rare. Thankfully it falls from the sky.
+
+Hopefully you have located yourself somewhere near a large water source as it will be essential for bread production. If not, rainfall could be collected by the community. in this case, large amounts of water storage would be necessary to offset any droughts. Attempt to secure some kind of tanker. Since the water is to be heated, it doesn't need to be sterile, but any solids in it will be left as a part of the dough when the water evaporates. A simple water filter using organic material should be enough for the bread itself, and bringing it to a rolling boil for a few minutes will make it drinkable.
+
+Chemicals could be used to make a large amount of water drinkable at once, Chlorine dioxide or household bleach could be used for this. On a smaller scale, UV sterilization would be effective. Utilizing either the sun's rays, or a dedicated sterilizer. Aquariums and pet shops selling fish could be one way of acquiring both chemical, and UV sterilization equipment.
+## Yeast and levaining
+
+A large amount of yeast will be available and is common is every supermarket and in many homes. Try to initially get as much as possible. It will not last long and will die within the year so should be used as much as possible. Conveniently, the amount of yeast is completely arbitrary and effects only how long it takes to make the bread. I would suggest using it as a backup for bread needed within around 2 hours time, as using sourdough will not be as flexible.
+
+Depending on the situation, some form of brewing operation may be setup nearby may be able to provide leavening, produced as a byproduct as the brewing process.
+
+### Sourdough
+
+Sourdough starter is perfect for a long-term operation, taking very little flour to keep alive and proving you with limitless levaining power. Usually sourdough bread will use 10-20% starter, but this could be reduced in the event of a flour shortage. We can therefore calculate that per kg of dough we would only need as little as 30g of starter for optimum ferment, also requiring us to feed the starter 15g of starter daily. This means that for approximately every 100 loafs of bread made, we will need to sacrifice a household bag of flour for levaining.
+
+The calculations here will most likely be very inaccurate, but it should be easy enough to work out the most effective use of flour for you with what you have access to, as this will be vastly different community to community.
+
+It should be noted that sourdough is digested by the body differently. During the fermentation process acetic acid is produced by LAB bacteria, making it easier to digest by the body. This manifests in decreased effect on coeliac disease or other gluten intolerance.
+
+## Salt
+
+Salt is a common ingredient in bread, and makes it palatable. In white bread I would usually use somewhere between 1-2%, and 1.5-2.5% in wholemeal or rye bread. Salt should be easy to acquire in mass from supermarkets. It keeps as long as its not exposed to moisture and will probably not be on peoples minds while searching for food.
+
+If it is not available, sea salt can be made easily from saltwater. If your location is nearby a source of saltwater, try to acquire tarps or flat baking tins. A car park or flat roof could be easily cleaned and used as a large salt pan if necessary.
+
+Salt has beneficial properties with other foods (lactose-fermentation, curing &c) and would be in demand for other uses than baking bread, simply stockpiling a large amount of salt would not be enough in the long term and some dedicated operation should be setup to supplement this.
+
+## Seeds and other additives
+
+Remember that most grains and seeds can be incorporated into bread through soaking, so along with flour try to find as much of these as possible. Pet stores and large supermarkets will stock large amounts of birdseed such as sunflower seeds and peanuts which will be safe for human consumption when cooked and are a good source of protein. Rice or potatoes could be used, but may just be more nutritious if just cooked and eaten regularly.
+
+Soaking is the process of soaking any additives in water for an hour before incorporating them into the bread dough. This ensures that that are already saturated with water and will not draw water away from the yeast.
+
+If it can be found, grains such as rye, wheat and spelt should be ground into flour, but if a grindstone was unavailable could simply be incorporated whole via soaking.
+
+Where seeds are organic, either from specialty stores or grown as part of a conscious effort, sprouting them before incorporating them into the bread can provide a far greater nutritional value. This takes only additional water and is well worth the effort.
+
+# The recipe
+
+The bread that you actually make will not be that important, and the classic "artisan sourdough" will be completely impractical. The only priority is now: make as much bread as possible with as little waste as possible. This means making the most use of the ingredients available to you, which will be completely different community to community.
+
+## Bakers percentage
+
+When working out recipes to be used to make an arbitrary amount of bread, instead of using a unit of weight (grams, pounds &c) we use percent. This allows us to come up with a recipe that is consistent at any scale. The total amount of flour is 100% and is the ruler we use to measure out the rest of the ingredients. For example we might use 60% flour, 10% starter and 2% yeast. At this point, if we know the total weight of bread we want to make
+
+For most, you will probably have far more wholemeal flour than plain white flour and plain white should be mixed in in small amounts to enhance the gluten content and offset wholemeal flour's higher absorption.
+
+Water should be used in moderation, as a higher hydration loaf will take longer to cook for each unit of flour. For example: A 50% loaf and a 70% loaf of equivalent weight will take the same about of time and space to cook, but the 70% will have approximately 12% more flour and therefore 12% more nutrients.
+
+Seeds and other additives should be used as much as possible, both to incorporate other nutrients but also to reduce the amount of flour used per loaf. Seeds and grains can both be incorporated via soaking (described above in "Seeds and additives"). When using this method the hydration percentage is based off both the flour and the seed weight. if your hydration is 70% without seeds, if you add 10% seeds, you should adjust your hydration to 77% (because 70% of 110% is 77%).
+
+Other than these general pointers, it is up to the community what bread they make. Generally, its difficult to make bread that is inedible, especially if there is little food and the people you feed will, I'm sure, be happy to offer plenty of advice like "more salt" or "could you use sesame seeds?".
+
+# Fermenting and Proofing
+
+In large scale artisan bakeries, dough is fermented at mass within large seal-able containers. This would be completely practical for us, and a large amount of plastic boxes or storage crates could be procured within almost any town or city. Bread dough will double is size during fermentation and as an approximation for our purposes, the weight of the bread is equivalent to its volume. (The actual figure is difficult to calculate as flour is particulate so the dry volume is vastly different to the volume when mixed with water.)
+
+Proofing is slightly more difficult due to to the fact you have to separate out the loafs, meaning they take up far more space. We can therefore consider 3 options.
+
+## Bannetons
+
+A banneton is a reed basket floured to stop the dough sticking to it, it can also be lined with a floured piece of cloth. For our purposes, a common plastic mixing bowl or strainer and a tea towel would be sufficient. If more Bannetons where required, one could be woven out of reed found throughout the world. This option does limit the bread's size and shape, although aesthetics will not be the most important thing to be worrying about.
+
+## Tins
+
+Bread tins would be an easy to use and consistent tool for proofing bread, and more than enough could be procured with the help of neighbors. Even if more where desperately needed, cake tins and saucepans would work just as well. The downside to this is getting the cooked bread out of the tin. Usually, I would grease up the sides of the tin before proofing, however access to oil might be difficult, especially once the supplies that can be acquired from nearby shops dry up.
+
+## Proof on surface
+
+A method that i have seen done in commercial bakeries is proofing directly on a surface and allowing the gluten to hold enough of its shape during proof time. This limits the maximum hydration of the dough but allows us to effectively proof our dough with little space used and no consumables other than flour.
+
+A Couche could also be used. This is a large cloth used to proof baguettes and batards. A fold is created in the sheet to separate the loafs.
+
+As a release agent, to keep the bread from sticking to the surface, regular glutenous flour can be used. Preferably, a substitute like rice flour or bran should be used to make it as easy as possible to release the bread from the surface, whole wheat and low gluten flours could also be used, but may not be as effective.
+
+# Baking
+
+Whether under the strain of widespread change or via intentional sabotage, I find it difficult to believe that the power grid would stay a consistent source of energy. With access to a steady stream of flowing water, however, access to a dependable source of energy is also secured. A source of energy that has mechanically powered large-scale production since the fourth-century BC. With a property within half a kilometer of flowing water, upwards of 10kW could be secured. Enough to power our entire community bakery as well as comfortably housing its caretakers.
+
+The tool used to bake the bread will depend on what is available to you. A nearby takeaway may have a pizza oven, but this may not be suitable due to its large energy consumption. The advantage of hydroelectricity is a consistent and dependable source of energy throughout the day and this should be used as much as possible. An assortment of average household ovens (each approx. 2kW), further insulated to increase efficiency, would be more than enough for our community-scale bakery.
+
+If using an alternate source of power, such as solar, larger batches in the day would be prioritized and bread production would have to be reduced In the winter months.
+
+## Fire
+
+In a situation where electricity is unfeasible it may be easier to go back to basics. Ovens are very simple to construct with basic building materials and a large capacity oven could be built from just a few paving slabs and bricks.
+
+Bread in the late middle ages was baked in what was called a faggot oven which used small bundles of sticks that burned fast and hot to heat up a chamber, which could then be swept of ashes and the residual heat used to bake bread. It requires only an insulated area with thick stone walls. It is more suited to higher capacity batch production.
+
+Alongside these furn ovens where also used. Open at the front with a fire kept lit either at the back, or below the cooking area. Because of its consistent heat, food could be baked continuously and over a longer time. The construction of both of these ovens is simple, and could be achieved very quickly and with little effort.
+
+Using a piece of scrap 6mm steel, some bricks and mud, I was able to build a very simple and capable oven. I used metal sheet because i wanted a cooking surface as well as a furn style oven compartment. This oven is suitable for no more than 4kg of bread dough and is pretty crude, but the bricks that built the mansions of the capitalists could build a far larger, more beautiful oven.
+
+## Solar Power
+
+Solar power is a source of energy unlikely to be affected by large scale infrastructure collapse. Not only that but the complete lack of petrol and diesel for consumer use will inevitably cause most cars to become unusable, each containing a 500Wh battery, good for 2 years. An array of 10 car batteries could keep a fridge running overnight while remaining above 50% charge.
+
+Currently, however, solar power largely depends on the grid, especially at the peak of winter, when solar panels can have as little as one hour of useful sunlight. This means that they are an effective secondary source for low power, low priority, situations.
+
+Its feels important to say, that in the event of full collapse, combustion based dependable electricity is completely impractical at any kind of scale. Even with a glut of car batteries and the nearest solar power plant, equipment will begin to malfunction and eventually fail. Without constant production modern infrastructure is unlikely to last more than a generation. The use of electricity here, then, is to ease us into a lifestyle of more physical labor, rather than replace the luxury of the grid. Not to say that there will be no electricity, but as convenient and fun as it is, wide-scale dependence will flood the world and kill us all.
diff --git a/site/src/niceones.md b/site/src/niceones.md
new file mode 100644 (file)
index 0000000..fa5e99d
--- /dev/null
@@ -0,0 +1,12 @@
+title: some nice website examples
+keywords: examples,meta 
+
+# Hello!
+
+Here are some nice websites:
+
+- <https://arrc.site/o%20o%20o%20o%20o%20o%20o%20o%20o%20o.html>
+- <https://takeawalkonthewildside.rietveldacademie.nl/>
+- <https://example.com>
+- <https://example.com>
+- <https://example.com>
diff --git a/site/src/plotter.md b/site/src/plotter.md
new file mode 100644 (file)
index 0000000..4eb7d86
--- /dev/null
@@ -0,0 +1,9 @@
+title: Bad plotter
+keywords: art
+date: 25/11/2023
+
+![image](/plotter/drawing.jpg "Drawing")
+
+![image](/plotter/minkey.jpg "Origional image")
+
+<iframe src="https://www.youtube.com/embed/HvuOEtforTQ?si=Pg3Cl2QgOC4z_RCr" frameborder="0" allowfullscreen></iframe>
diff --git a/site/src/porn.md b/site/src/porn.md
new file mode 100644 (file)
index 0000000..63f3189
--- /dev/null
@@ -0,0 +1,102 @@
+title: Abstain
+keywords: programming,art
+date: 24/05/2025
+
+I would strike Jesus out on 3 pitches. Cumshot complation, he feels like hes drowning. Forbidden fruit in the garden of eden, of course he's taking it. And bang 5:22 (1 Thessalonians) inside corner. We're mixing body oil and holy water today with the league leader in BPB[^1] and the biggest sin pit this side of the river Styx.
+
+**You're out!**
+
+# Markov chain poems from PornHub and the Good Book (WIP)
+
+It's a great read! And the bibles good too, I guess. Play Ball!
+
+[TOC]
+
+## Introduction
+
+> like the stars be concealed with it's riches.<br>
+> and a fog who overtake it,<br>
+> or who have made into level ways.<br>
+> And who makes a call<br>
+><br>
+> and in the desert,<br>
+> or from the mouth.<br>
+> the sons of israel,<br>
+> may swallow us whole<br>
+><br>
+> And those who hate hard sex<br>
+> Lord, lead me forth,<br>
+> Show me a fith time,<br>
+> in the midst of the earth,<br>
+><br>
+> and set her land the rivers have spoiled.<br>
+> and fucked her throat from being human,<br>
+> and when they had no one to see<br>
+> Show me your heart, like a whore<br>
+><br>
+> big ass, slobbered pussy<br>
+> Show me a learned tongue,<br>
+> Show hospitality to one another,<br>
+> to riding and grinding like Crazy!<br>
+><br>
+> and one saint said to Saul:<br>
+> "Why should he who is lifted up the blood,<br>
+> not go down to the south<br>
+> and we have Cum on Face Complation - Load Moaning asking Cum !"<br>
+> for the appointed days<br>
+> she closed the door on the desert,<br>
+> And when you are my god,<br>
+> le t there be wild lesbian sex.<br>
+
+Markov chains look at language like a graph and work out that, in this sentence, the word "the" is followed by the word "word" 33.33% of the time, "is" 16.17% of the time and "time" 50% of the time.
+
+That way, if i give you the start of a sentence: "When I woke up, the", you can roll your dice and work out which word its followed by. "When I woke up, the word".
+
+This is the tech behind phone auto-complete and the game of pressing the middle option till a sentence comes out.
+
+For maximum accuracy, the chain needs to be trained on as large a dataset as possible, examining each sentence for the connections between words and updating its look-book.
+
+I trained one markov chain on the bible and one on 20 thousand porn titles and made them kiss.
+
+## Method
+
+### Aggregating data
+
+I put together a quick script to scrape through the recomendation API page by page and sift out the data. This was easy[^3]. As for the bible, many versions are available in plain-text.
+
+### Post-processing
+
+As well as producing a chain for each, I also reversed each line of the data and produced a chain from each of those, allowing be to run the chain backwards if I wanted to generate sequences that ended on a specific word. I imagined this would have been useful for specifically generating poems.
+
+Some small amount of clean-up was done after testing the system, paticularly to remove rougue characters that would put the chains into a spin. Emojis were left in.
+
+### Generating chains
+
+I used the rust crate "markov"[^2] to generate the actual chains in a variety of ways. I tried generating based on the first word, generating based on the last word, generating based on the middle word and getting each chain to work outwards to produce some result.
+
+Almost all of the time it would be either bible or porn and what I was looking for was a mixture between the two. It seemed like certain trigger words would allow the system to switch between the two. "a" was the most effective of these, "have", "her", "the" and "on" were also useful.
+
+I selected my favorates and printed them out, cutting up each line and occasionally lines into smaller parts to arrange into order.
+
+## Result
+
+Two of my favorates are above and below.
+
+> Show me your penis!<br>
+> It's for my boyfriend,<br>
+> Show this video to you name.<br>
+> Show him my intricate laws,<br>
+><br>
+> Show me your heart,<br>
+> Show me the tumult ceased, Paul,<br>
+> cute australian kitty shows up<br>
+> who sits upon the wall<br>
+><br>
+> Show him my creampied pussy<br>
+> Show me a leaned tongue,<br>
+> they will not always hold this power<br>
+> Show hospitality to one another.<br>
+
+[^1]: Little known SABRmetric: "Books Per Book"
+[^2]: <https://docs.rs/markov/>
+[^3]: I origionally planned to scrape 4 times as much data from the PornHub website, but I must have been scraping too hard because they noticed me.
diff --git a/site/src/smoked.md b/site/src/smoked.md
new file mode 100644 (file)
index 0000000..17bbc0e
--- /dev/null
@@ -0,0 +1,13 @@
+title: Smoked Breads
+keywords: bread
+date: 19/11/2023
+
+Kimbell, in her book, mentions that there are two ways of going about smoking bread: "Smoke the grains before you mill them" or "Smoke the loaf whole". The first apparently imbues the entire loaf with the smokey flavor, with the second mostly affecting the crust.
+
+I had some maple lying around, picked up as scrap from a local violin repair shop and intended to be used to make a couple sets of straight razor scales. I whittled it down and collected the shavings, ending up with a couple grams of maple chip. My smoker was 2 foil turkey roasting trays, the bottom one with a couple holes stabbed in it, sitting on one of my baking steels on top of the hob.
+
+The smoke lasted only a couple of minutes, before all the wood was burned and the bread started to cook further. It would be better to have a proper setup to cold smoke them as it left the crusts thick and the bottom charred. It tasted disappointing at first, but after being left to cool, the flavor really came out. It tasted like I was eating it with smoked cheese and bacon fat. Definitely a choice flavor, paired with a slow-fermented rye mite I think it would be amazing, but it definitely seems strange with a plain white yeasted bread.
+
+When back at home, there is an apple tree nearby that needs to be chopped down, if I take some fresh trimmings and weld up a crude smoke-box, I should be able to make some really nice smoked breads.
+
+![image](/smoked/ciabatta.jpg "The bread")
diff --git a/site/src/stft.md b/site/src/stft.md
new file mode 100644 (file)
index 0000000..50e1539
--- /dev/null
@@ -0,0 +1,39 @@
+title: Audio over Video
+keywords: programming,audio,art
+date: 03/10/2024
+
+Hello!
+
+This is an old post moved from the old blog. But there is more to say now.
+
+<iframe src="https://www.youtube.com/embed/acxykQsh8cw?si=vtFPepZPFSAg_bgR"></iframe>
+
+# The idea
+
+One day I was thinking about if you could move audio over video. Surely it was a far more information dense media? Possibly not?[^1]
+
+I did the napkin maths on a stream of QR codes rushing past, then samples expressed in colours. This would be an easy route. When i thought about it properly, though, it seemed less than intuitive. The whole idea (at this point) was to have the audience interact with the sound in real-time, but what would they be able to do with multi-color noise? Only subtractive interaction. Not good enough.
+
+## Spectograms
+
+Spectrograms! This would be perfect! Very intuitive.. They are made through the fourrier transform, which splits a signal into its frequency components.
+
+I eventually finished building an inital version in python after a year and a half of prototypes. This is all mirrored in the git logs[^2]. Bear in mind I'd already been trying for half a year of on-off work before I finally committed to version management haha.
+
+This proved to be very slow, my laptop at the time had 4GB of RAM so that was probaby part of it.
+
+![image](/stft/demo.jpg "A demo in a house I miss")
+
+I showed this to one of my lectrurers working as a sound artist, he told me to do a pilot exibition and put me in contact with the buildings broadcast engineer.
+
+I decided to learn rust and do a full rewrite. This was actually far faster and more intuitve than the Python and it not only came together quicker, but was massively faster. Especcially considering I had to learn the basics of the language first. This version is in a seperate git repo[^3].
+
+The broadcast engineer was impressed, offered me building space and put me in contact with someone else in the building who might be able to help. At the end of this final meeting, with this final contact, and 2 years of writes and re-writes, I was told it was good. "Find some people to work with" he told me "Y'Know, take over a space!" and he was right! But I don't want to be an artist. I've realised. So i'm taking advice from the commissioners: Kill your babies.
+
+Maybe some day i'll do that pilot exibition, might be fun.
+
+![image](/stft/forest.jpg "The calibration forest")
+
+[^1]: This was around 2 years ago as I write this (04/03/2025).
+[^2]: <https://git.ozva.co.uk/?p=audio-over-stft>
+[^3]: <https://git.ozva.co.uk/?p=rust_fft>
diff --git a/site/src/weber.md b/site/src/weber.md
new file mode 100644 (file)
index 0000000..e426773
--- /dev/null
@@ -0,0 +1,15 @@
+title: The Protagonist of Bowling
+keywords: bowling,radio
+date: 19/11/2023
+
+![image](/weber/weber.jpg "Pete Weber in 2012")
+
+> It's the 10th frame of the 2012 US open finals and Mike Fagan just got 3 strikes in a row.
+>
+> Pete Weber steps up to bowl. He has to get a spare and then a strike to win.
+>
+> Pete Weber, known as PDW, is trying for his 5th US open title over 4 decades, more than any bowler before or since has won.
+
+Pete Weber: The protagonist of bowling is a short radio documentary I wrote and produced in my first week of University, it is arguably the best piece of radio I've ever made (20 November 2023). Soundtracked by Underworld.
+
+It is currently available on my [Soundcloud](https://soundcloud.com/will-greenwood-896086623) and streaming on [XMDV Radio](https://xmdv.ozva.co.uk/).
diff --git a/site/static/favicon.ico b/site/static/favicon.ico
new file mode 100644 (file)
index 0000000..58ea0ba
Binary files /dev/null and b/site/static/favicon.ico differ
diff --git a/site/static/font.css b/site/static/font.css
new file mode 100644 (file)
index 0000000..4248f6d
--- /dev/null
@@ -0,0 +1,129 @@
+@font-face {
+       font-family: 'Work Sans';
+       src: url('/static/fonts/WorkSans-Thin.ttf') format('truetype');
+       font-weight: 200;
+       font-display: swap;
+       font-style: normal;
+}
+@font-face {
+       font-family: 'Work Sans';
+       src: url('/static/fonts/WorkSans-ThinItalic.ttf') format('truetype');
+       font-weight: 200;
+       font-display: swap;
+       font-style: italic;
+}
+@font-face {
+  font-family: 'Work Sans';
+  src: url('/static/fonts/WorkSans-ExtraLight.ttf') format('truetype');
+  font-weight: 200;
+  font-display: swap;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'Work Sans';
+  src: url('/static/fonts/WorkSans-ExtraLightItalic.ttf') format('truetype');
+  font-weight: 200;
+  font-display: swap;
+  font-style: italic;
+}
+@font-face {
+  font-family: 'Work Sans';
+  src: url('/static/fonts/WorkSans-Light.woff2') format('woff2'),
+       url('/static/fonts/WorkSans-Light.woff') format('woff'),
+       url('/static/fonts/WorkSans-Light.ttf') format('truetype');
+  font-weight: 300;
+  font-display: swap;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'Work Sans';
+  src: url('/static/fonts/WorkSans-LightItalic.ttf') format('truetype');
+  font-weight: 300;
+  font-display: swap;
+  font-style: italic;
+}
+@font-face {
+  font-family: 'Work Sans';
+  src: url('/static/fonts/WorkSans-Regular.ttf') format('truetype');
+  font-weight: 400;
+  font-display: swap;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'Work Sans';
+  src: url('/static/fonts/WorkSans-Italic.ttf') format('truetype');
+  font-weight: 400;
+  font-display: swap;
+  font-style: italic;
+}
+@font-face {
+  font-family: 'Work Sans';
+  src: url('/static/fonts/WorkSans-Medium.ttf') format('truetype');
+  font-weight: 550;
+  font-display: swap;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'Work Sans';
+  src: url('/static/fonts/WorkSans-MediumItalic.ttf') format('truetype');
+  font-weight: 550;
+  font-display: swap;
+  font-style: italic;
+}
+@font-face {
+  font-family: 'Work Sans';
+  src: url('/static/fonts/WorkSans-SemiBold.ttf') format('truetype');
+  font-weight: 700;
+  font-display: swap;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'Work Sans';
+  src: url('/static/fonts/WorkSans-SemiBoldItalic.ttf') format('truetype');
+  font-weight: 700;
+  font-display: swap;
+  font-style: italic;
+}
+@font-face {
+  font-family: 'Work Sans';
+  src: url('/static/fonts/WorkSans-Bold.ttf') format('truetype');
+  font-weight: 800;
+  font-display: swap;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'Work Sans';
+  src: url('/static/fonts/WorkSans-BoldItalic.ttf') format('truetype');
+  font-weight: 800;
+  font-display: swap;
+  font-style: italic;
+}
+@font-face {
+  font-family: 'Work Sans';
+  src: url('/static/fonts/WorkSans-ExtraBold.ttf') format('truetype');
+  font-weight: 850;
+  font-display: swap;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'Work Sans';
+  src: url('/static/fonts/WorkSans-ExtraBoldItalic.ttf') format('truetype');
+  font-weight: 850;
+  font-display: swap;
+  font-style: italic;
+}
+@font-face {
+  font-family: 'Work Sans';
+  src: url('/static/fonts/WorkSans-Black.ttf') format('truetype');
+  font-weight: 900;
+  font-display: swap;
+  font-style: normal;
+}
+@font-face {
+  font-family: 'Work Sans';
+  src: url('/static/fonts/WorkSans-BlackItalic.ttf') format('truetype');
+  font-weight: 900;
+  font-display: swap;
+  font-style: italic;
+}
+
diff --git a/site/static/fonts/Literata-Black.eot b/site/static/fonts/Literata-Black.eot
deleted file mode 100644 (file)
index cfa05cc..0000000
Binary files a/site/static/fonts/Literata-Black.eot and /dev/null differ
diff --git a/site/static/fonts/Literata-Black.ttf b/site/static/fonts/Literata-Black.ttf
deleted file mode 100644 (file)
index 4b252fd..0000000
Binary files a/site/static/fonts/Literata-Black.ttf and /dev/null differ
diff --git a/site/static/fonts/Literata-Black.woff b/site/static/fonts/Literata-Black.woff
deleted file mode 100644 (file)
index 391f006..0000000
Binary files a/site/static/fonts/Literata-Black.woff and /dev/null differ
diff --git a/site/static/fonts/Literata-Black.woff2 b/site/static/fonts/Literata-Black.woff2
deleted file mode 100644 (file)
index 9ee0c2f..0000000
Binary files a/site/static/fonts/Literata-Black.woff2 and /dev/null differ
diff --git a/site/static/fonts/Literata-BlackItalic.eot b/site/static/fonts/Literata-BlackItalic.eot
deleted file mode 100644 (file)
index 87af5ba..0000000
Binary files a/site/static/fonts/Literata-BlackItalic.eot and /dev/null differ
diff --git a/site/static/fonts/Literata-BlackItalic.ttf b/site/static/fonts/Literata-BlackItalic.ttf
deleted file mode 100644 (file)
index 07bd93d..0000000
Binary files a/site/static/fonts/Literata-BlackItalic.ttf and /dev/null differ
diff --git a/site/static/fonts/Literata-BlackItalic.woff b/site/static/fonts/Literata-BlackItalic.woff
deleted file mode 100644 (file)
index 8bba61a..0000000
Binary files a/site/static/fonts/Literata-BlackItalic.woff and /dev/null differ
diff --git a/site/static/fonts/Literata-BlackItalic.woff2 b/site/static/fonts/Literata-BlackItalic.woff2
deleted file mode 100644 (file)
index 9036559..0000000
Binary files a/site/static/fonts/Literata-BlackItalic.woff2 and /dev/null differ
diff --git a/site/static/fonts/Literata-Bold.eot b/site/static/fonts/Literata-Bold.eot
deleted file mode 100644 (file)
index 2539bac..0000000
Binary files a/site/static/fonts/Literata-Bold.eot and /dev/null differ
diff --git a/site/static/fonts/Literata-Bold.ttf b/site/static/fonts/Literata-Bold.ttf
deleted file mode 100644 (file)
index b6253ff..0000000
Binary files a/site/static/fonts/Literata-Bold.ttf and /dev/null differ
diff --git a/site/static/fonts/Literata-Bold.woff b/site/static/fonts/Literata-Bold.woff
deleted file mode 100644 (file)
index 9437314..0000000
Binary files a/site/static/fonts/Literata-Bold.woff and /dev/null differ
diff --git a/site/static/fonts/Literata-Bold.woff2 b/site/static/fonts/Literata-Bold.woff2
deleted file mode 100644 (file)
index ef5b8c1..0000000
Binary files a/site/static/fonts/Literata-Bold.woff2 and /dev/null differ
diff --git a/site/static/fonts/Literata-BoldItalic.eot b/site/static/fonts/Literata-BoldItalic.eot
deleted file mode 100644 (file)
index 1ca1ed0..0000000
Binary files a/site/static/fonts/Literata-BoldItalic.eot and /dev/null differ
diff --git a/site/static/fonts/Literata-BoldItalic.ttf b/site/static/fonts/Literata-BoldItalic.ttf
deleted file mode 100644 (file)
index a22e7da..0000000
Binary files a/site/static/fonts/Literata-BoldItalic.ttf and /dev/null differ
diff --git a/site/static/fonts/Literata-BoldItalic.woff b/site/static/fonts/Literata-BoldItalic.woff
deleted file mode 100644 (file)
index e18c2e5..0000000
Binary files a/site/static/fonts/Literata-BoldItalic.woff and /dev/null differ
diff --git a/site/static/fonts/Literata-BoldItalic.woff2 b/site/static/fonts/Literata-BoldItalic.woff2
deleted file mode 100644 (file)
index a71f1e4..0000000
Binary files a/site/static/fonts/Literata-BoldItalic.woff2 and /dev/null differ
diff --git a/site/static/fonts/Literata-ExtraBold.eot b/site/static/fonts/Literata-ExtraBold.eot
deleted file mode 100644 (file)
index bebc7a5..0000000
Binary files a/site/static/fonts/Literata-ExtraBold.eot and /dev/null differ
diff --git a/site/static/fonts/Literata-ExtraBold.ttf b/site/static/fonts/Literata-ExtraBold.ttf
deleted file mode 100644 (file)
index 9863ef8..0000000
Binary files a/site/static/fonts/Literata-ExtraBold.ttf and /dev/null differ
diff --git a/site/static/fonts/Literata-ExtraBold.woff b/site/static/fonts/Literata-ExtraBold.woff
deleted file mode 100644 (file)
index a8b8fc4..0000000
Binary files a/site/static/fonts/Literata-ExtraBold.woff and /dev/null differ
diff --git a/site/static/fonts/Literata-ExtraBold.woff2 b/site/static/fonts/Literata-ExtraBold.woff2
deleted file mode 100644 (file)
index 9bddb28..0000000
Binary files a/site/static/fonts/Literata-ExtraBold.woff2 and /dev/null differ
diff --git a/site/static/fonts/Literata-ExtraBoldItalic.eot b/site/static/fonts/Literata-ExtraBoldItalic.eot
deleted file mode 100644 (file)
index b626708..0000000
Binary files a/site/static/fonts/Literata-ExtraBoldItalic.eot and /dev/null differ
diff --git a/site/static/fonts/Literata-ExtraBoldItalic.ttf b/site/static/fonts/Literata-ExtraBoldItalic.ttf
deleted file mode 100644 (file)
index e036f9b..0000000
Binary files a/site/static/fonts/Literata-ExtraBoldItalic.ttf and /dev/null differ
diff --git a/site/static/fonts/Literata-ExtraBoldItalic.woff b/site/static/fonts/Literata-ExtraBoldItalic.woff
deleted file mode 100644 (file)
index 25624df..0000000
Binary files a/site/static/fonts/Literata-ExtraBoldItalic.woff and /dev/null differ
diff --git a/site/static/fonts/Literata-ExtraBoldItalic.woff2 b/site/static/fonts/Literata-ExtraBoldItalic.woff2
deleted file mode 100644 (file)
index 96287c4..0000000
Binary files a/site/static/fonts/Literata-ExtraBoldItalic.woff2 and /dev/null differ
diff --git a/site/static/fonts/Literata-ExtraLight.eot b/site/static/fonts/Literata-ExtraLight.eot
deleted file mode 100644 (file)
index add5128..0000000
Binary files a/site/static/fonts/Literata-ExtraLight.eot and /dev/null differ
diff --git a/site/static/fonts/Literata-ExtraLight.ttf b/site/static/fonts/Literata-ExtraLight.ttf
deleted file mode 100644 (file)
index 3e54364..0000000
Binary files a/site/static/fonts/Literata-ExtraLight.ttf and /dev/null differ
diff --git a/site/static/fonts/Literata-ExtraLight.woff b/site/static/fonts/Literata-ExtraLight.woff
deleted file mode 100644 (file)
index 24f660c..0000000
Binary files a/site/static/fonts/Literata-ExtraLight.woff and /dev/null differ
diff --git a/site/static/fonts/Literata-ExtraLight.woff2 b/site/static/fonts/Literata-ExtraLight.woff2
deleted file mode 100644 (file)
index 19f4d93..0000000
Binary files a/site/static/fonts/Literata-ExtraLight.woff2 and /dev/null differ
diff --git a/site/static/fonts/Literata-ExtraLightItalic.eot b/site/static/fonts/Literata-ExtraLightItalic.eot
deleted file mode 100644 (file)
index d6c6bf1..0000000
Binary files a/site/static/fonts/Literata-ExtraLightItalic.eot and /dev/null differ
diff --git a/site/static/fonts/Literata-ExtraLightItalic.ttf b/site/static/fonts/Literata-ExtraLightItalic.ttf
deleted file mode 100644 (file)
index 335f614..0000000
Binary files a/site/static/fonts/Literata-ExtraLightItalic.ttf and /dev/null differ
diff --git a/site/static/fonts/Literata-ExtraLightItalic.woff b/site/static/fonts/Literata-ExtraLightItalic.woff
deleted file mode 100644 (file)
index 640178b..0000000
Binary files a/site/static/fonts/Literata-ExtraLightItalic.woff and /dev/null differ
diff --git a/site/static/fonts/Literata-ExtraLightItalic.woff2 b/site/static/fonts/Literata-ExtraLightItalic.woff2
deleted file mode 100644 (file)
index 20c37db..0000000
Binary files a/site/static/fonts/Literata-ExtraLightItalic.woff2 and /dev/null differ
diff --git a/site/static/fonts/Literata-Italic.eot b/site/static/fonts/Literata-Italic.eot
deleted file mode 100644 (file)
index 9ddba22..0000000
Binary files a/site/static/fonts/Literata-Italic.eot and /dev/null differ
diff --git a/site/static/fonts/Literata-Italic.ttf b/site/static/fonts/Literata-Italic.ttf
deleted file mode 100644 (file)
index 7c5fad9..0000000
Binary files a/site/static/fonts/Literata-Italic.ttf and /dev/null differ
diff --git a/site/static/fonts/Literata-Italic.woff b/site/static/fonts/Literata-Italic.woff
deleted file mode 100644 (file)
index 39035c8..0000000
Binary files a/site/static/fonts/Literata-Italic.woff and /dev/null differ
diff --git a/site/static/fonts/Literata-Italic.woff2 b/site/static/fonts/Literata-Italic.woff2
deleted file mode 100644 (file)
index 9086be3..0000000
Binary files a/site/static/fonts/Literata-Italic.woff2 and /dev/null differ
diff --git a/site/static/fonts/Literata-Light.eot b/site/static/fonts/Literata-Light.eot
deleted file mode 100644 (file)
index 8e10d8b..0000000
Binary files a/site/static/fonts/Literata-Light.eot and /dev/null differ
diff --git a/site/static/fonts/Literata-Light.ttf b/site/static/fonts/Literata-Light.ttf
deleted file mode 100644 (file)
index 31b2f46..0000000
Binary files a/site/static/fonts/Literata-Light.ttf and /dev/null differ
diff --git a/site/static/fonts/Literata-Light.woff b/site/static/fonts/Literata-Light.woff
deleted file mode 100644 (file)
index d8660bf..0000000
Binary files a/site/static/fonts/Literata-Light.woff and /dev/null differ
diff --git a/site/static/fonts/Literata-Light.woff2 b/site/static/fonts/Literata-Light.woff2
deleted file mode 100644 (file)
index 02dac30..0000000
Binary files a/site/static/fonts/Literata-Light.woff2 and /dev/null differ
diff --git a/site/static/fonts/Literata-LightItalic.eot b/site/static/fonts/Literata-LightItalic.eot
deleted file mode 100644 (file)
index 44afed9..0000000
Binary files a/site/static/fonts/Literata-LightItalic.eot and /dev/null differ
diff --git a/site/static/fonts/Literata-LightItalic.ttf b/site/static/fonts/Literata-LightItalic.ttf
deleted file mode 100644 (file)
index 0cecb80..0000000
Binary files a/site/static/fonts/Literata-LightItalic.ttf and /dev/null differ
diff --git a/site/static/fonts/Literata-LightItalic.woff b/site/static/fonts/Literata-LightItalic.woff
deleted file mode 100644 (file)
index f9e2703..0000000
Binary files a/site/static/fonts/Literata-LightItalic.woff and /dev/null differ
diff --git a/site/static/fonts/Literata-LightItalic.woff2 b/site/static/fonts/Literata-LightItalic.woff2
deleted file mode 100644 (file)
index 2302ccb..0000000
Binary files a/site/static/fonts/Literata-LightItalic.woff2 and /dev/null differ
diff --git a/site/static/fonts/Literata-Medium.eot b/site/static/fonts/Literata-Medium.eot
deleted file mode 100644 (file)
index 183b63c..0000000
Binary files a/site/static/fonts/Literata-Medium.eot and /dev/null differ
diff --git a/site/static/fonts/Literata-Medium.ttf b/site/static/fonts/Literata-Medium.ttf
deleted file mode 100644 (file)
index 44c8b1c..0000000
Binary files a/site/static/fonts/Literata-Medium.ttf and /dev/null differ
diff --git a/site/static/fonts/Literata-Medium.woff b/site/static/fonts/Literata-Medium.woff
deleted file mode 100644 (file)
index 02a1e3e..0000000
Binary files a/site/static/fonts/Literata-Medium.woff and /dev/null differ
diff --git a/site/static/fonts/Literata-Medium.woff2 b/site/static/fonts/Literata-Medium.woff2
deleted file mode 100644 (file)
index a39b62a..0000000
Binary files a/site/static/fonts/Literata-Medium.woff2 and /dev/null differ
diff --git a/site/static/fonts/Literata-MediumItalic.eot b/site/static/fonts/Literata-MediumItalic.eot
deleted file mode 100644 (file)
index c983ef2..0000000
Binary files a/site/static/fonts/Literata-MediumItalic.eot and /dev/null differ
diff --git a/site/static/fonts/Literata-MediumItalic.ttf b/site/static/fonts/Literata-MediumItalic.ttf
deleted file mode 100644 (file)
index ee2c36a..0000000
Binary files a/site/static/fonts/Literata-MediumItalic.ttf and /dev/null differ
diff --git a/site/static/fonts/Literata-MediumItalic.woff b/site/static/fonts/Literata-MediumItalic.woff
deleted file mode 100644 (file)
index 56867e0..0000000
Binary files a/site/static/fonts/Literata-MediumItalic.woff and /dev/null differ
diff --git a/site/static/fonts/Literata-MediumItalic.woff2 b/site/static/fonts/Literata-MediumItalic.woff2
deleted file mode 100644 (file)
index 7466e57..0000000
Binary files a/site/static/fonts/Literata-MediumItalic.woff2 and /dev/null differ
diff --git a/site/static/fonts/Literata-Regular.eot b/site/static/fonts/Literata-Regular.eot
deleted file mode 100644 (file)
index 7683e6e..0000000
Binary files a/site/static/fonts/Literata-Regular.eot and /dev/null differ
diff --git a/site/static/fonts/Literata-Regular.ttf b/site/static/fonts/Literata-Regular.ttf
deleted file mode 100644 (file)
index 4f23c45..0000000
Binary files a/site/static/fonts/Literata-Regular.ttf and /dev/null differ
diff --git a/site/static/fonts/Literata-Regular.woff b/site/static/fonts/Literata-Regular.woff
deleted file mode 100644 (file)
index 7176b40..0000000
Binary files a/site/static/fonts/Literata-Regular.woff and /dev/null differ
diff --git a/site/static/fonts/Literata-Regular.woff2 b/site/static/fonts/Literata-Regular.woff2
deleted file mode 100644 (file)
index b549628..0000000
Binary files a/site/static/fonts/Literata-Regular.woff2 and /dev/null differ
diff --git a/site/static/fonts/Literata-SemiBold.eot b/site/static/fonts/Literata-SemiBold.eot
deleted file mode 100644 (file)
index 3b0a21b..0000000
Binary files a/site/static/fonts/Literata-SemiBold.eot and /dev/null differ
diff --git a/site/static/fonts/Literata-SemiBold.ttf b/site/static/fonts/Literata-SemiBold.ttf
deleted file mode 100644 (file)
index 673ca79..0000000
Binary files a/site/static/fonts/Literata-SemiBold.ttf and /dev/null differ
diff --git a/site/static/fonts/Literata-SemiBold.woff b/site/static/fonts/Literata-SemiBold.woff
deleted file mode 100644 (file)
index 6f36970..0000000
Binary files a/site/static/fonts/Literata-SemiBold.woff and /dev/null differ
diff --git a/site/static/fonts/Literata-SemiBold.woff2 b/site/static/fonts/Literata-SemiBold.woff2
deleted file mode 100644 (file)
index 19f5bfd..0000000
Binary files a/site/static/fonts/Literata-SemiBold.woff2 and /dev/null differ
diff --git a/site/static/fonts/Literata-SemiBoldItalic.eot b/site/static/fonts/Literata-SemiBoldItalic.eot
deleted file mode 100644 (file)
index 4854e97..0000000
Binary files a/site/static/fonts/Literata-SemiBoldItalic.eot and /dev/null differ
diff --git a/site/static/fonts/Literata-SemiBoldItalic.ttf b/site/static/fonts/Literata-SemiBoldItalic.ttf
deleted file mode 100644 (file)
index e954961..0000000
Binary files a/site/static/fonts/Literata-SemiBoldItalic.ttf and /dev/null differ
diff --git a/site/static/fonts/Literata-SemiBoldItalic.woff b/site/static/fonts/Literata-SemiBoldItalic.woff
deleted file mode 100644 (file)
index e298270..0000000
Binary files a/site/static/fonts/Literata-SemiBoldItalic.woff and /dev/null differ
diff --git a/site/static/fonts/Literata-SemiBoldItalic.woff2 b/site/static/fonts/Literata-SemiBoldItalic.woff2
deleted file mode 100644 (file)
index 86f90a0..0000000
Binary files a/site/static/fonts/Literata-SemiBoldItalic.woff2 and /dev/null differ
diff --git a/site/static/fonts/Literata-Variable.eot b/site/static/fonts/Literata-Variable.eot
deleted file mode 100644 (file)
index 9b4af18..0000000
Binary files a/site/static/fonts/Literata-Variable.eot and /dev/null differ
diff --git a/site/static/fonts/Literata-Variable.ttf b/site/static/fonts/Literata-Variable.ttf
deleted file mode 100644 (file)
index a703bcf..0000000
Binary files a/site/static/fonts/Literata-Variable.ttf and /dev/null differ
diff --git a/site/static/fonts/Literata-Variable.woff b/site/static/fonts/Literata-Variable.woff
deleted file mode 100644 (file)
index 7b8901c..0000000
Binary files a/site/static/fonts/Literata-Variable.woff and /dev/null differ
diff --git a/site/static/fonts/Literata-Variable.woff2 b/site/static/fonts/Literata-Variable.woff2
deleted file mode 100644 (file)
index 4c38eb8..0000000
Binary files a/site/static/fonts/Literata-Variable.woff2 and /dev/null differ
diff --git a/site/static/fonts/Literata-VariableItalic.eot b/site/static/fonts/Literata-VariableItalic.eot
deleted file mode 100644 (file)
index c7dd657..0000000
Binary files a/site/static/fonts/Literata-VariableItalic.eot and /dev/null differ
diff --git a/site/static/fonts/Literata-VariableItalic.ttf b/site/static/fonts/Literata-VariableItalic.ttf
deleted file mode 100644 (file)
index dd9b012..0000000
Binary files a/site/static/fonts/Literata-VariableItalic.ttf and /dev/null differ
diff --git a/site/static/fonts/Literata-VariableItalic.woff b/site/static/fonts/Literata-VariableItalic.woff
deleted file mode 100644 (file)
index e9cac9a..0000000
Binary files a/site/static/fonts/Literata-VariableItalic.woff and /dev/null differ
diff --git a/site/static/fonts/Literata-VariableItalic.woff2 b/site/static/fonts/Literata-VariableItalic.woff2
deleted file mode 100644 (file)
index f80ed3e..0000000
Binary files a/site/static/fonts/Literata-VariableItalic.woff2 and /dev/null differ
diff --git a/site/static/fonts/WorkSans-Black.ttf b/site/static/fonts/WorkSans-Black.ttf
new file mode 100644 (file)
index 0000000..4ddbd0a
Binary files /dev/null and b/site/static/fonts/WorkSans-Black.ttf differ
diff --git a/site/static/fonts/WorkSans-BlackItalic.ttf b/site/static/fonts/WorkSans-BlackItalic.ttf
new file mode 100644 (file)
index 0000000..690950c
Binary files /dev/null and b/site/static/fonts/WorkSans-BlackItalic.ttf differ
diff --git a/site/static/fonts/WorkSans-Bold.ttf b/site/static/fonts/WorkSans-Bold.ttf
new file mode 100644 (file)
index 0000000..5c97989
Binary files /dev/null and b/site/static/fonts/WorkSans-Bold.ttf differ
diff --git a/site/static/fonts/WorkSans-BoldItalic.ttf b/site/static/fonts/WorkSans-BoldItalic.ttf
new file mode 100644 (file)
index 0000000..54418b8
Binary files /dev/null and b/site/static/fonts/WorkSans-BoldItalic.ttf differ
diff --git a/site/static/fonts/WorkSans-ExtraBold.ttf b/site/static/fonts/WorkSans-ExtraBold.ttf
new file mode 100644 (file)
index 0000000..6dc6fca
Binary files /dev/null and b/site/static/fonts/WorkSans-ExtraBold.ttf differ
diff --git a/site/static/fonts/WorkSans-ExtraBoldItalic.ttf b/site/static/fonts/WorkSans-ExtraBoldItalic.ttf
new file mode 100644 (file)
index 0000000..258233f
Binary files /dev/null and b/site/static/fonts/WorkSans-ExtraBoldItalic.ttf differ
diff --git a/site/static/fonts/WorkSans-ExtraLight.ttf b/site/static/fonts/WorkSans-ExtraLight.ttf
new file mode 100644 (file)
index 0000000..a6d4617
Binary files /dev/null and b/site/static/fonts/WorkSans-ExtraLight.ttf differ
diff --git a/site/static/fonts/WorkSans-ExtraLightItalic.ttf b/site/static/fonts/WorkSans-ExtraLightItalic.ttf
new file mode 100644 (file)
index 0000000..d5f300c
Binary files /dev/null and b/site/static/fonts/WorkSans-ExtraLightItalic.ttf differ
diff --git a/site/static/fonts/WorkSans-Italic.ttf b/site/static/fonts/WorkSans-Italic.ttf
new file mode 100644 (file)
index 0000000..40529b6
Binary files /dev/null and b/site/static/fonts/WorkSans-Italic.ttf differ
diff --git a/site/static/fonts/WorkSans-Light.ttf b/site/static/fonts/WorkSans-Light.ttf
new file mode 100644 (file)
index 0000000..1fe1fd1
Binary files /dev/null and b/site/static/fonts/WorkSans-Light.ttf differ
diff --git a/site/static/fonts/WorkSans-LightItalic.ttf b/site/static/fonts/WorkSans-LightItalic.ttf
new file mode 100644 (file)
index 0000000..d70036f
Binary files /dev/null and b/site/static/fonts/WorkSans-LightItalic.ttf differ
diff --git a/site/static/fonts/WorkSans-Medium.ttf b/site/static/fonts/WorkSans-Medium.ttf
new file mode 100644 (file)
index 0000000..2168073
Binary files /dev/null and b/site/static/fonts/WorkSans-Medium.ttf differ
diff --git a/site/static/fonts/WorkSans-MediumItalic.ttf b/site/static/fonts/WorkSans-MediumItalic.ttf
new file mode 100644 (file)
index 0000000..dc6944c
Binary files /dev/null and b/site/static/fonts/WorkSans-MediumItalic.ttf differ
diff --git a/site/static/fonts/WorkSans-Regular.ttf b/site/static/fonts/WorkSans-Regular.ttf
new file mode 100644 (file)
index 0000000..d24586c
Binary files /dev/null and b/site/static/fonts/WorkSans-Regular.ttf differ
diff --git a/site/static/fonts/WorkSans-SemiBold.ttf b/site/static/fonts/WorkSans-SemiBold.ttf
new file mode 100644 (file)
index 0000000..a75721c
Binary files /dev/null and b/site/static/fonts/WorkSans-SemiBold.ttf differ
diff --git a/site/static/fonts/WorkSans-SemiBoldItalic.ttf b/site/static/fonts/WorkSans-SemiBoldItalic.ttf
new file mode 100644 (file)
index 0000000..7d07062
Binary files /dev/null and b/site/static/fonts/WorkSans-SemiBoldItalic.ttf differ
diff --git a/site/static/fonts/WorkSans-Thin.ttf b/site/static/fonts/WorkSans-Thin.ttf
new file mode 100644 (file)
index 0000000..a097d7c
Binary files /dev/null and b/site/static/fonts/WorkSans-Thin.ttf differ
diff --git a/site/static/fonts/WorkSans-ThinItalic.ttf b/site/static/fonts/WorkSans-ThinItalic.ttf
new file mode 100644 (file)
index 0000000..1fe9f79
Binary files /dev/null and b/site/static/fonts/WorkSans-ThinItalic.ttf differ
diff --git a/site/static/literata.css b/site/static/literata.css
deleted file mode 100644 (file)
index 5a1cd85..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/**
-* Literata ExtraLight 
-* Literata ExtraLightItalic 
-* Literata Light 
-* Literata LightItalic 
-* Literata Regular 
-* Literata Italic 
-* Literata Medium 
-* Literata MediumItalic 
-* Literata SemiBold 
-* Literata SemiBoldItalic 
-* Literata Bold 
-* Literata BoldItalic 
-* Literata ExtraBold 
-* Literata ExtraBoldItalic 
-* Literata Black 
-* Literata BlackItalic
-**/
-
-@font-face {
-  font-family: 'Literata';
-  src: url('/static/fonts/Literata-ExtraLight.woff2') format('woff2'),
-       url('/static/fonts/Literata-ExtraLight.woff') format('woff'),
-       url('/static/fonts/Literata-ExtraLight.ttf') format('truetype');
-  font-weight: 200;
-  font-display: swap;
-  font-style: normal;
-}
-@font-face {
-  font-family: 'Literata';
-  src: url('/static/fonts/Literata-ExtraLightItalic.woff2') format('woff2'),
-       url('/static/fonts/Literata-ExtraLightItalic.woff') format('woff'),
-       url('/static/fonts/Literata-ExtraLightItalic.ttf') format('truetype');
-  font-weight: 200;
-  font-display: swap;
-  font-style: italic;
-}
-@font-face {
-  font-family: 'Literata';
-  src: url('/static/fonts/Literata-Light.woff2') format('woff2'),
-       url('/static/fonts/Literata-Light.woff') format('woff'),
-       url('/static/fonts/Literata-Light.ttf') format('truetype');
-  font-weight: 300;
-  font-display: swap;
-  font-style: normal;
-}
-@font-face {
-  font-family: 'Literata';
-  src: url('/static/fonts/Literata-LightItalic.woff2') format('woff2'),
-       url('/static/fonts/Literata-LightItalic.woff') format('woff'),
-       url('/static/fonts/Literata-LightItalic.ttf') format('truetype');
-  font-weight: 300;
-  font-display: swap;
-  font-style: italic;
-}
-@font-face {
-  font-family: 'Literata';
-  src: url('/static/fonts/Literata-Regular.woff2') format('woff2'),
-       url('/static/fonts/Literata-Regular.woff') format('woff'),
-       url('/static/fonts/Literata-Regular.ttf') format('truetype');
-  font-weight: 400;
-  font-display: swap;
-  font-style: normal;
-}
-@font-face {
-  font-family: 'Literata';
-  src: url('/static/fonts/Literata-Italic.woff2') format('woff2'),
-       url('/static/fonts/Literata-Italic.woff') format('woff'),
-       url('/static/fonts/Literata-Italic.ttf') format('truetype');
-  font-weight: 400;
-  font-display: swap;
-  font-style: italic;
-}
-@font-face {
-  font-family: 'Literata';
-  src: url('/static/fonts/Literata-Medium.woff2') format('woff2'),
-       url('/static/fonts/Literata-Medium.woff') format('woff'),
-       url('/static/fonts/Literata-Medium.ttf') format('truetype');
-  font-weight: 550;
-  font-display: swap;
-  font-style: normal;
-}
-@font-face {
-  font-family: 'Literata';
-  src: url('/static/fonts/Literata-MediumItalic.woff2') format('woff2'),
-       url('/static/fonts/Literata-MediumItalic.woff') format('woff'),
-       url('/static/fonts/Literata-MediumItalic.ttf') format('truetype');
-  font-weight: 550;
-  font-display: swap;
-  font-style: italic;
-}
-@font-face {
-  font-family: 'Literata';
-  src: url('/static/fonts/Literata-SemiBold.woff2') format('woff2'),
-       url('/static/fonts/Literata-SemiBold.woff') format('woff'),
-       url('/static/fonts/Literata-SemiBold.ttf') format('truetype');
-  font-weight: 700;
-  font-display: swap;
-  font-style: normal;
-}
-@font-face {
-  font-family: 'Literata';
-  src: url('/static/fonts/Literata-SemiBoldItalic.woff2') format('woff2'),
-       url('/static/fonts/Literata-SemiBoldItalic.woff') format('woff'),
-       url('/static/fonts/Literata-SemiBoldItalic.ttf') format('truetype');
-  font-weight: 700;
-  font-display: swap;
-  font-style: italic;
-}
-@font-face {
-  font-family: 'Literata';
-  src: url('/static/fonts/Literata-Bold.woff2') format('woff2'),
-       url('/static/fonts/Literata-Bold.woff') format('woff'),
-       url('/static/fonts/Literata-Bold.ttf') format('truetype');
-  font-weight: 800;
-  font-display: swap;
-  font-style: normal;
-}
-@font-face {
-  font-family: 'Literata';
-  src: url('/static/fonts/Literata-BoldItalic.woff2') format('woff2'),
-       url('/static/fonts/Literata-BoldItalic.woff') format('woff'),
-       url('/static/fonts/Literata-BoldItalic.ttf') format('truetype');
-  font-weight: 800;
-  font-display: swap;
-  font-style: italic;
-}
-@font-face {
-  font-family: 'Literata';
-  src: url('/static/fonts/Literata-ExtraBold.woff2') format('woff2'),
-       url('/static/fonts/Literata-ExtraBold.woff') format('woff'),
-       url('/static/fonts/Literata-ExtraBold.ttf') format('truetype');
-  font-weight: 850;
-  font-display: swap;
-  font-style: normal;
-}
-@font-face {
-  font-family: 'Literata';
-  src: url('/static/fonts/Literata-ExtraBoldItalic.woff2') format('woff2'),
-       url('/static/fonts/Literata-ExtraBoldItalic.woff') format('woff'),
-       url('/static/fonts/Literata-ExtraBoldItalic.ttf') format('truetype');
-  font-weight: 850;
-  font-display: swap;
-  font-style: italic;
-}
-@font-face {
-  font-family: 'Literata';
-  src: url('/static/fonts/Literata-Black.woff2') format('woff2'),
-       url('/static/fonts/Literata-Black.woff') format('woff'),
-       url('/static/fonts/Literata-Black.ttf') format('truetype');
-  font-weight: 900;
-  font-display: swap;
-  font-style: normal;
-}
-@font-face {
-  font-family: 'Literata';
-  src: url('/static/fonts/Literata-BlackItalic.woff2') format('woff2'),
-       url('/static/fonts/Literata-BlackItalic.woff') format('woff'),
-       url('/static/fonts/Literata-BlackItalic.ttf') format('truetype');
-  font-weight: 900;
-  font-display: swap;
-  font-style: italic;
-}
-
diff --git a/site/static/query.css b/site/static/query.css
new file mode 100644 (file)
index 0000000..9c716cf
--- /dev/null
@@ -0,0 +1,43 @@
+@media (max-width: 750px) {
+       #extra {
+       display: none;
+       }
+       aside {
+               padding: 10px;
+               border-bottom: 2px solid var(--primary);
+       }
+       main {
+               padding: 10px;
+       }
+}
+
+@media (min-width: 750px) {
+       aside {
+               position: absolute;
+               top: 0;
+               bottom: 0;
+               left: 5%;
+               right: 70%;
+               padding: 10px;
+               overflow: scroll;
+       }
+       main {
+               position: absolute;
+               top: 0;
+               bottom: 0;
+               left: 30%;
+               right: 0;
+               padding: 10px;
+               overflow: scroll;
+       }
+       main > div {
+               margin-left: auto;
+               margin-right: 10%;}
+       }
+
+@media (prefers-color-scheme: dark) {
+       :root {
+               --primary: white;
+               --background: var(--black);
+       }
+}
index a1c241ebe89553e2e2c08672c15a89d6b37ffb42..5f45a5200e46dcf30e89c6cf337093fae70d16e6 100644 (file)
@@ -1,23 +1,25 @@
-const links = document.getElementsByTagName('a');
+function addPrefetch () {
+       const links = document.getElementsByTagName('a');
 
-for (anchor of links) {
-    anchor.addEventListener('mouseover', event => {
-        const href = event.target.href;
+       for (anchor of links) {
+               anchor.addEventListener('mouseover', event => {
+                       const href = event.target.href;
 
-        const link = document.createElement('link');
-        link.rel = 'prefetch';
-        link.href = href;
+                       const link = document.createElement('link');
+                       link.rel = 'preload';
+                       link.href = href;
 
-        document.head.appendChild(link);
-    });
+                       document.head.appendChild(link);
+               });
 
-    anchor.addEventListener('touchstart', event => {
-        const href = event.target.href;
+               anchor.addEventListener('touchstart', event => {
+                       const href = event.target.href;
 
-        const link = document.createElement('link');
-        link.rel = 'prefetch';
-        link.href = href;
+                       const link = document.createElement('link');
+                       link.rel = 'preload';
+                       link.href = href;
 
-        document.head.appendChild(link);
-    });
+                       document.head.appendChild(link);
+               });
+       }
 }
index 0a79aab3309eb1e6442103df0e214a0e7e3861f3..11aa9b29481c2c2c81da65309f59cacedc5a4966 100644 (file)
@@ -1,15 +1,21 @@
+/* ========================================================================== */
+/* Variables */
+
 :root {
     --black: #111111;
-    --blue: blue;
+    --blue: #0000FF;
 
     --primary: var(--black);
     --secondary: #252525;
-    --background: white;
+    --background: #FFFFFF;
 }
 
+/* ========================================================================== */
+/* Type */
+
 body {
     margin: 0;
-    font-family: "Literata", serif;
+    font-family: "Work Sans", sans-serif;
     color: var(--primary);
     background-color: var(--background);
 }
@@ -18,67 +24,43 @@ body {
     font-size: 2.8em;
 }
 
-@media (max-width: 750px) {
-    #extra {
-    display: none;
-    }
-    nav {
-        padding: 10px;
-        border-bottom: 2px solid var(--primary);
-    }
-    main {
-        padding: 10px;
-    }
-}
-
-@media (min-width: 750px) {
-    nav {
-        position: absolute;
-        top: 0;
-        bottom: 0;
-        left: 0;
-        right: 75%;
-        padding: 10px;
-        overflow: scroll;
-        border-right: 2px solid var(--primary);
-    }
-    main {
-        position: absolute;
-        top: 0;
-        bottom: 0;
-        left: 25%;
-        right: 0;
-        padding: 10px;
-        overflow: scroll;
-    }
-}
-
-main > *:not(hr) {
-    width: min(100%, 700px);
+/* ========================================================================== */
+/* Layout */
+
+main > * {
+       width: 90%;
+       text-align: right;
+}
+
+main > div {
+       margin-top: 100px;
+       width: min(100%, 55em);
+       text-align: left;
 }
+
 main > div > p {
+       margin: 0;
+       text-indent: 1.5em;
     text-align: justify;
     text-justify: inter-word;
 }
 
-code {
-    text-align: left;
-    text-justify: none;
+/* stop the line immediately below a heading from indenting */
+h1 + p, h2 + p, h3 + p, h4 + p, h5 + p, h6 + p, p:first-of-type {
+       text-indent: 0 !important;
 }
 
-a:link {
-    color: var(--blue);
-    transition: color 0.25s, background-color 0.25s;
-}
-a:visited {
-    color: var(--black);
-}
-a:hover {
-    color: white;
-    background-color: var(--blue);
+/* ========================================================================== */
+/* Standard layout styling */
+
+audio {
+       margin: 10px 0 10px -1.5em;
+       width: 100%;
 }
-a:active {
-    color: var(--blue);
+
+code {
+    text-align: left;
+    text-justify: none;
 }
 
 hr {
@@ -101,9 +83,25 @@ blockquote > p {
     margin: 0
 }
 
-@media (prefers-color-scheme: dark) {
-    :root {
-        --primary: white;
-        --background: var(--black);
-    }
+h1 {
+       margin-block: 0.67em;
+       font-size: 2em;
+}
+
+/* ========================================================================== */
+/* Link Styling */
+
+a:link {
+       color: var(--blue);
+       transition: color 0.25s, background-color 0.25s;
+}
+a:visited {
+       color: var(--black);
+}
+a:hover {
+       color: white;
+       background-color: var(--blue);
+}
+a:active {
+       color: var(--blue);
 }
diff --git a/site/templates/homepage.md b/site/templates/homepage.md
deleted file mode 100644 (file)
index 66e4275..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-# Hello this is the homepage
-
-![image](/homepage/challah.jpg "The world has already ended.")
-![image](/homepage/fruit.jpg "Follow Teeth.")
index 37ddcafec8c9cf7741d95835d33463db1fabc62e..baa452d02647892293a7e0c85387f5813b76e338 100644 (file)
@@ -2,47 +2,36 @@
 <html>
        <head>
                <title>{{title}}</title>
+               <link rel="stylesheet" href="static/font.css">
                <link rel="stylesheet" href="static/style.css">
-               <link rel="stylesheet" href="static/literata.css">
+               <link rel="stylesheet" href="static/query.css">
                <script src="static/script.js"></script>
+
+               <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
        </head>
-       <body>
-               <nav>
-                       <h1>Will Greenwood</h1>
-                       <p>Blog - <a href="/">Home</a> - <a href="/categories">Categories</a></p>
+       <body> <!-- addPrefetch(); !-->
+               <aside>
+                       <h1><a href="/">Chester Robert Demo</a></h1>
                        <search>
-                       <form action="./search">
-                               <input type="search" name="name" />
-                               <button type="submit">Search</button>
-                       </form>
+                               <form action="./search">
+                                       <input type="search" name="name" />
+                                       <button type="submit">Search</button>
+                               </form>
                        </search>
                        <div id="extra">
-                               <hr>
-                               <h3>History:</h3>
-                               {{history|safe}}
                                {{sidebar|safe}}
                        </div>
-               </nav><main>
+               </aside><main>
                        <h1 class='mainTitle'>{{title}}</h1>
                        {% if date %}
                        <h2>{{date}}</h2>
                        {% endif %}
-                       {% if abstract %}
-                       <p>Abstract: <em>{{abstract}}</em></p>
-                       {% endif %}
                        {% if keywords %}
-                       <p>Keywords: <em>{{keywords|safe}}<br><a href="/categories">See more keywords...</a></em><br></p>
-                       {% endif %}
-                       {% if filename %}
-                       <p><a href="https://git.ozva.co.uk/?p=blog;a=history;f=pages/{{filename|safe}}.md">&#9921; <em>See page history...</em></a></p>
+                       <p>Tags: <em>{{keywords|safe}}</em></p>
                        {% endif %}
-                       <hr>
                        <div>
                                {{content|safe}}
                        </div>
-                       <p>
-                               &copy; William Greenwood 2024
-                       </p>
                </main>
        </body>
 </html>