diff --git a/content/about.md b/content/about.md
index 76f2acb..b9c5bd5 100644
--- a/content/about.md
+++ b/content/about.md
@@ -5,7 +5,6 @@ timeless = true
comments = false
aliases = ["tldr", "bio"]
+++
-
![Me, +/- a few decades](/images/john.jpg)
You've (somehow) managed to stumble upon my dark corner of the internet[^1].
@@ -22,20 +21,21 @@ On weekends, I race my daily-driven 2014 Subaru BRZ in local [autocross events](
And in the free time I have left, I game on my Steam Deck.
-See what I've been up to on:
+### See what I've been up to on:
- [GitHub](https://github.com/jbowdre)
-- [Scribbles 'n Bits](https://scribbes.jbowdre.lol)
+- [Scribbles 'n Bits](https://scribbles.jbowdre.lol)
- [status.lol](https://status.jbowdre.lol)
- [social.lol](https://social.lol/@jbowdre)
- [CounterSocial](https://counter.social/@john_b)
- [/now](https://now.jbowdre.lol)
-Connect with me via:
+### Connect with me via:
- [SimpleX Chat](/simplex/)
- [Signal](https://signal.me/#eu/lyHZbMnlM16O0w48j3rshYBofO0K-iXOt9LGwln7TS-fNKEHCrxH3La325q8IjRU)
- [Matrix](https://matrix.to/#/@jbowdre:omg.lol)
- [XMPP](https://conversations.im/i/jbowdre@omg.lol?omemo-sid-1374125881=a620f3c57733601a6646f6f13a71c86fc9be8dd4126fd158ef3e0a26beb0b434)
- [Electronic Mail](mailto:jbowdre@omg.lol)
- [PGP: 613F B70C 4FA7 A077](https://l.runtimeterror.dev/pgp)
+
[^1]: Congrats? And also, *thank you.*
[^2]: A bit. I'm still in the "fake it until you make" it phase of adulthood.
diff --git a/content/posts/automating-camera-notifications-home-assistant-ntfy/index.md b/content/posts/automating-camera-notifications-home-assistant-ntfy/index.md
index 0e7073f..3184794 100644
--- a/content/posts/automating-camera-notifications-home-assistant-ntfy/index.md
+++ b/content/posts/automating-camera-notifications-home-assistant-ntfy/index.md
@@ -134,6 +134,7 @@ homeassistant:
```
I'm using the [Home Assistant Operating System virtual appliance](https://www.home-assistant.io/installation/alternative#install-home-assistant-operating-system), so `/media` is already symlinked to `/root/media` inside the Home Assistant installation directory. So I'll just log into that shell and create the `snaps` subdirectory:
+
```shell
mkdir -p /media/snaps # [tl! .cmd_root]
```
@@ -149,6 +150,7 @@ Now that I've captured the snap, I need to figure out how to attach it to the no
I can't use the handy `!secret` expansion inside of the shell command, though, so I'll need a workaround to avoid sticking sensitive details directly in my `configuration.yaml`. I can use a dummy sensor to hold the value, and then use the `{{ states('sensor.$sensor_name') }}` template to retrieve it.
So here we go:
+
```yaml
# configuration.yaml [tl! focus:start]
@@ -180,6 +182,7 @@ shell_command: # [tl! focus:9 highlight:6,1]
```
Now I just need to replace the service call in the automation with the new `shell_command.ntfy_put` one:
+
```yaml
# torchlight! {"lineNumbers": true}
# exterior_motion.yaml # [tl! focus]
@@ -230,6 +233,7 @@ Well that guy seems sus - but hey, it worked!
Of course, I'll also continue to get notified about that creeper in the backyard about every 15-20 seconds or so. That's not quite what I want. The _easy_ way to prevent an automation from firing constantly would be to [insert a `delay`](https://www.home-assistant.io/docs/scripts/#wait-for-time-to-pass-delay) action, but that would be a global delay rather than per-camera. I don't necessarily need to know every time the weirdo in the backyard moves, but I would like to know if he moves around to the side yard or driveway. So I needed something more flexible than an automation-wide delay.
Instead, I'll create a 5-minute [`timer`](https://www.home-assistant.io/integrations/timer/) for each camera by simply adding this to my `configuration.yaml`:
+
```yaml
# configuration.yaml
timer:
@@ -310,6 +314,7 @@ That pretty much takes care of my needs for exterior motion alerts, and should k
### Managing interior alerts
I've got a few interior cameras which I'd like to monitor too, so I'll start by just copying the exterior automation and updating the entity IDs:
+
```yaml
# torchlight! {"lineNumbers": true}
# interior_motion.yaml
@@ -361,6 +366,7 @@ But I don't typically want to get alerted by these cameras if my wife or I are h
![calendar](schedule.png)
So then I'll just add another condition so that the automation will only fire during those calendar events:
+
```yaml
# torchlight! {"lineNumbers": true}
# interior_motion.yaml [tl! focus]
@@ -517,6 +523,7 @@ icon: mdi:alarm-snooze
I can then add that script to the camera dashboard in Home Assistant or pin it to the home controls on my Android phone for easy access.
I'll also create another script for manually toggling interior alerts for when we're home at an odd time:
+
```yaml
# torchlight! {"lineNumbers": true}
# toggle_interior_alerts.yaml
diff --git a/content/simplex.md b/content/simplex.md
index 4937533..c27283b 100644
--- a/content/simplex.md
+++ b/content/simplex.md
@@ -8,7 +8,7 @@ showReadTime = false
timeless = true
title = "SimpleX Chat"
+++
-*You can **[contact me on SimpleX Chat](https://l.runtimeterror.dev/simplex-chat-invite)** by clicking that link or scanning the QR code below.*
+> You can [contact me on SimpleX Chat](https://l.runtimeterror.dev/simplex-chat-invite) by clicking that link or scanning the QR code below.
![QR code](/images/simplex-invite.png)
@@ -28,9 +28,9 @@ Just add these in the SimpleX app at **Settings > Network & servers > SMP server
`smp://kYx5LmVD9FMM8hJN4BQqL4WmeUNZn8ipXsX2UkBoiHE=@smp.vpota.to`
-| | |
-| --- | --- |
-| [![Uptime](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjbowdre%2Fupptime%2Fmaster%2Fapi%2Fsmp-vpota-to-5223%2Fuptime.json)](https://status.runtimeterror.dev/history/smp-vpota-to-5223) | [[netdata](https://l.runtimeterror.dev/smp_status)] |
+[![Uptime](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjbowdre%2Fupptime%2Fmaster%2Fapi%2Fsmp-vpota-to-5223%2Fuptime.json)](https://status.runtimeterror.dev/history/smp-vpota-to-5223)
+
+[netdata](https://l.runtimeterror.dev/smp_status)
---
@@ -38,9 +38,9 @@ Just add these in the SimpleX app at **Settings > Network & servers > SMP server
`smp://TbUrGydawdVKID0Lvix14UkaN-WarFgqXx4kaEG8Trw=@smp1.vpota.to`
-| | |
-| --- | --- |
-| [![Uptime](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjbowdre%2Fupptime%2Fmaster%2Fapi%2Fsmp1-vpota-to-5223%2Fuptime.json)](https://status.runtimeterror.dev/history/smp1-vpota-to-5223) | [[netdata](https://l.runtimeterror.dev/smp1_status)] |
+[![Uptime](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjbowdre%2Fupptime%2Fmaster%2Fapi%2Fsmp1-vpota-to-5223%2Fuptime.json)](https://status.runtimeterror.dev/history/smp1-vpota-to-5223)
+
+[netdata](https://l.runtimeterror.dev/smp1_status)
---
@@ -48,6 +48,6 @@ Just add these in the SimpleX app at **Settings > Network & servers > SMP server
`smp://tNfQisxTQ9MhKpFDTbx9RnjgWigtxF1a26jroy5-rR4=@smp2.vpota.to`
-| | |
-| --- | --- |
-| [![Uptime](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjbowdre%2Fupptime%2Fmaster%2Fapi%2Fsmp2-vpota-to-5223%2Fuptime.json)](https://status.runtimeterror.dev/history/smp2-vpota-to-5223) | [[netdata](https://l.runtimeterror.dev/smp2_status)] |
+[![Uptime](https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjbowdre%2Fupptime%2Fmaster%2Fapi%2Fsmp2-vpota-to-5223%2Fuptime.json)](https://status.runtimeterror.dev/history/smp2-vpota-to-5223)
+
+[netdata](https://l.runtimeterror.dev/smp2_status)
diff --git a/layouts/_default/single.gmi b/layouts/_default/single.gmi
index b63727d..9462f0b 100644
--- a/layouts/_default/single.gmi
+++ b/layouts/_default/single.gmi
@@ -1,5 +1,4 @@
=> / 💻 [runtimeterror $]
-
# {{ .Title }}{{ $scratch := newScratch }}
{{- if .Params.Date }}
{{- $postDate := .Date.Format "2006-01-02" }}
@@ -8,35 +7,44 @@
{{- end }}
{{/* The bulk of this regex magic is derived from https://brainbaking.com/post/2021/04/using-hugo-to-launch-a-gemini-capsule/ */}}
{{ $content := .RawContent -}}
-{{ $content := $content | replaceRE `#### ` "### " -}}
-{{ $content := $content | replaceRE `\n- (.+?)` "\n* $1" -}}
-{{ $content := $content | replaceRE `\n(\d+). (.+?)` "\n* $2" -}}
-{{ $content := $content | replaceRE `\[\^(.+?)\]:.*\n?\n?` "" -}}
-{{ $content := $content | replaceRE `\[\^(.+?)\]` "" -}}
-{{ $content := $content | replaceRE `
` "\n" -}}
-{{ $content := $content | replaceRE `\{\{%\s\/?notice.*%\}\}` "***" -}}
-{{ $content := $content | replaceRE `((\/\/)|#)\s*torchlight!.*` "" -}}
-{{ $content := $content | replaceRE `` "" -}}
-{{ $content := $content | replaceRE `\/\/\s*\[tl!.*\]` "" -}}
-{{ $content := $content | replaceRE `#\s*\[tl!.*\]` "" -}}
-{{ $content := $content | replaceRE `(.+?)` "[$2]($1)" -}}
-{{ $content := $content | replaceRE `\sgemini://(\S*)` " [gemini://$1](gemini://$1)" -}}
-{{ $content := $content | replaceRE `\n\*\s+\[(.+?)\]\((.+?)\)` "\n=> $2 $1" -}}
-{{/* $content := $content | replaceRE "([^`])<.*?>([^`])" "$1$2" -*/}}
-{{ $content := $content | replaceRE `\n+!\[.*\]\((.+?) \"(.+?)\"\)` "\n\n=> $1 Image: $2" -}}
-{{ $content := $content | replaceRE `\n+!\[.*\]\((.+?)\)` "\n\n=> $1 Embedded Image: $1" -}}
-{{ $links := findRE `\n=> ` $content }}{{ $scratch.Set "ref" (add (len $links) 1) }}
-{{ $refs := findRE `\[.+?\]\(.+?\)` $content }}
-{{ $scratch.Set "content" $content }}{{ range $refs }}{{ $ref := $scratch.Get "ref" }}{{ $contentInLoop := $scratch.Get "content" }}{{ $url := (printf "%s #%d" . $ref) }}{{ $contentInLoop := replace $contentInLoop . $url -}}{{ $scratch.Set "content" $contentInLoop }}{{ $scratch.Set "ref" (add $ref 1) }}{{ end }}{{ $content := $scratch.Get "content" | replaceRE `\[(.+?)\]\((.+?)\) #(\d+)` "$1 [$3]" -}}
-{{ $content | safeHTML }}
-
+{{- $content := $content | replaceRE `#{4,} ` "### " -}}{{/* reduce headings to a max of 3 levels */}}
+{{- $content := $content | replaceRE `(?m:^- (.+?)$)` "\n* $1" -}}{{/* convert unordered lists */}}
+{{- $content := $content | replaceRE `(?m:^(?:\d+). (.+?)$)` "* $1" -}}{{/* convert ordered lists */}}
+{{- $content := $content | replaceRE `\n\[\^(.+?)\]:\s.*` "" -}}{{/* remove footnote definitions */}}
+{{- $content := $content | replaceRE `\[\^(.+?)\]` "" -}}{{/* remove footnote anchors */}}
+{{- $content := $content | replaceRE "(?m:^`([^`]*)`$)" "```\n$1\n```\n" -}}{{/* convert single-line inline code to blocks */}}
+{{- $content := $content | replaceRE `\{\{%\snotice.*%\}\}` "<-- note -->" -}}{{/* convert hugo notices */}}
+{{- $content := $content | replaceRE `\{\{%\s/notice.*%\}\}` "<-- /note -->" -}}
+{{- $content := $content | replaceRE `((\/\/)|#)\s*torchlight!.*\n` "" -}}{{/* remove torchlight markup */}}
+{{- $content := $content | replaceRE `(?:(?: