commit f75f832bdf8a7967f5935fbf53e844d8d8f94f86
parent ecad8a35ecc759c3d59bec4efd959a6c79f69464
Author: Beau <cbeauhilton@gmail.com>
Date: Thu, 1 Dec 2022 14:42:34 -0600
small change to test build
Diffstat:
14 files changed, 2073 insertions(+), 0 deletions(-)
diff --git a/test/about/index.html b/test/about/index.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <link rel="stylesheet" href="/style.css" type="text/css">
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" type="text/css" href="/style.css">
+ <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E">
+ <title></title>
+ </head>
+ <body>
+ <div id="page-wrapper">
+ <div id="header" role="banner">
+ <header class="banner">
+ <div id="banner-text">
+ <span class="banner-title"><a href="/">beauhilton</a></span>
+ </div>
+ </header>
+ <nav>
+ <a class="nav-active" href="/about">about</a>
+<a href="/now">now</a>
+<a href="/posts">posts</a>
+<a href="https://notes.beauhilton.com">notes</a>
+<a href="https://talks.beauhilton.com">talks</a>
+<a href="https://git.beauhilton.com">git</a>
+<a href="/contact">contact</a>
+<a href="/feed.xml">rss</a>
+ </nav>
+ </div>
+ <main>
+ <h1>
+ about
+ </h1>
+ <p>
+ I’m a husband, father, physician, educator, and data scientist.
+ </p>
+ <h2>
+ husband and father
+ </h2>
+ <p>
+ These are the most important roles I play. If we meet, and you’re
+interested, we can talk about it.
+ </p>
+ <h2>
+ physician
+ </h2>
+ <p>
+ Medical school at Cleveland Clinic Lerner College of Medicine of Case
+Western Reserve University, Class of 2020.
+ </p>
+ <p>
+ Harrison Society member at Vanderbilt University, which includes
+internal medicine residency (2020-2022) and research/fellowship in
+hematology-oncology (2022-2026).
+ </p>
+ <h2>
+ educator
+ </h2>
+ <p>
+ Harvard Macy Institute faculty, 2018-present. Health Care Education
+2.0.
+ </p>
+ <h2>
+ data scientist
+ </h2>
+ <p>
+ Machine learning and data science approaches to diagnosis and
+prognosis of blood cancers; healthcare disparities in hospital medicine;
+predictive modeling of hospital readmissions and length of stay.
+ </p>
+ <p>
+ <a href="https://scholar.google.com/citations?user=Ng5AgXAAAAAJ">Google
+Scholar profile</a>
+ </p>
+ </main>
+ <div id="footnotes"></div>
+ <footer></footer>
+ </div>
+ </body>
+</html>
diff --git a/test/atom.xml b/test/atom.xml
@@ -0,0 +1,87 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
+ <id>https://soupault.app/atom.xml</id>
+ <title>beauhilton</title>
+ <updated>2022-11-13T00:00:00+00:00</updated>
+ <author>
+ <name>beau hilton</name>
+ <email>beau@beauhilton.com</email>
+ </author>
+ <generator uri="https://soupault.app" version="4.3.1">soupault</generator>
+ <logo>🏕️</logo>
+ <subtitle>beau's website</subtitle>
+ <entry>
+ <id>https://soupault.app/posts/mime</id>
+ <title>fix MIME Types to unbreak RSS feeds served by OpenBSD’s
+httpd(8)</title>
+ <updated>2022-11-13T00:00:00+00:00</updated>
+ <content type="html">
+ I've been getting back into RSS lately.
+Turns out, my own RSS feed was broken.
+ </content>
+ <link href="https://soupault.app/posts/mime" rel="alternate"/>
+ </entry>
+
+ <entry>
+ <id>https://soupault.app/posts/ugbsd</id>
+ <title>Upgrading out-of-date OpenBSD installs</title>
+ <updated>2022-11-11T00:00:00+00:00</updated>
+ <content type="html">
+ First of all, don't do how I do.
+Upgrade your installs regularly.
+OpenBSD makes it very easy.
+ </content>
+ <link href="https://soupault.app/posts/ugbsd" rel="alternate"/>
+ </entry>
+
+ <entry>
+ <id>https://soupault.app/posts/geocheatcode</id>
+ <title>geocheatcode</title>
+ <updated>2022-04-22T00:00:00+00:00</updated>
+ <content type="html">
+ Here is background and code
+for a trick I use to get
+Google to give me best-in-class guesses
+for latitude and longitude,
+despite goofy and/or downright bad location searches.
+ </content>
+ <link href="https://soupault.app/posts/geocheatcode" rel="alternate"/>
+ </entry>
+
+ <entry>
+ <id>https://soupault.app/posts/intake-2022-03-25</id>
+ <title>intake</title>
+ <updated>2022-03-25T00:00:00+00:00</updated>
+ <content type="html">
+ candidal esophagitis, achalasia, H Pylori PUD
+ </content>
+ <link href="https://soupault.app/posts/intake-2022-03-25" rel="alternate"/>
+ </entry>
+
+ <entry>
+ <id>https://soupault.app/posts/employee-wifi</id>
+ <title>Set Up Enterprise Wifi on Arch Linux</title>
+ <updated>2021-09-17T00:00:00+00:00</updated>
+ <content type="html">
+ Most big institutions have guest and employee wifi networks.
+Guest wifi is usually fine, fast enough for the basics,
+but far inferior to employee wifi.
+On a custom-built OS, such as a fairly minimalist Linux distribution,
+getting the employee wifi to work
+can be a beast.
+ </content>
+ <link href="https://soupault.app/posts/employee-wifi" rel="alternate"/>
+ </entry>
+
+ <entry>
+ <id>https://soupault.app/posts/mr-2021</id>
+ <title>Morning Report 08/23/2021</title>
+ <updated>2021-08-23T00:00:00+00:00</updated>
+ <content type="html">
+ Diagnosis is... MDS/MPN/MF NOS.
+i.e., who knows.
+ </content>
+ <link href="https://soupault.app/posts/mr-2021" rel="alternate"/>
+ </entry>
+
+</feed>
+\ No newline at end of file
diff --git a/test/contact/index.html b/test/contact/index.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <link rel="stylesheet" href="/style.css" type="text/css">
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" type="text/css" href="/style.css">
+ <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E">
+ <title></title>
+ </head>
+ <body>
+ <div id="page-wrapper">
+ <div id="header" role="banner">
+ <header class="banner">
+ <div id="banner-text">
+ <span class="banner-title"><a href="/">beauhilton</a></span>
+ </div>
+ </header>
+ <nav>
+ <a href="/about">about</a>
+<a href="/now">now</a>
+<a href="/posts">posts</a>
+<a href="https://notes.beauhilton.com">notes</a>
+<a href="https://talks.beauhilton.com">talks</a>
+<a href="https://git.beauhilton.com">git</a>
+<a class="nav-active" href="/contact">contact</a>
+<a href="/feed.xml">rss</a>
+ </nav>
+ </div>
+ <main>
+ <p>
+ This is my social media account.
+ </p>
+ <p>
+ If you want to get in touch, email: <a href="mailto:beau@beauhilton.com">beau@beauhilton.com</a>.
+ </p>
+ <p>
+ I’ll respond within the week.
+ </p>
+ </main>
+ <div id="footnotes"></div>
+ <footer></footer>
+ </div>
+ </body>
+</html>
diff --git a/test/index.html b/test/index.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <link rel="stylesheet" href="/style.css" type="text/css">
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" type="text/css" href="/style.css">
+ <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E">
+ <title></title>
+ </head>
+ <body>
+ <div id="page-wrapper">
+ <div id="header" role="banner">
+ <header class="banner">
+ <div id="banner-text">
+ <span class="banner-title"><a href="/">beauhilton</a></span>
+ </div>
+ </header>
+ <nav>
+ <a href="/about">about</a>
+<a href="/now">now</a>
+<a href="/posts">posts</a>
+<a href="https://notes.beauhilton.com">notes</a>
+<a href="https://talks.beauhilton.com">talks</a>
+<a href="https://git.beauhilton.com">git</a>
+<a href="/contact">contact</a>
+<a href="/feed.xml">rss</a>
+ </nav>
+ </div>
+ <main>
+ <br>
+ </main>
+ <div id="footnotes"></div>
+ <footer></footer>
+ </div>
+ </body>
+</html>
diff --git a/test/now/index.html b/test/now/index.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <link rel="stylesheet" href="/style.css" type="text/css">
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" type="text/css" href="/style.css">
+ <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E">
+ <title></title>
+ </head>
+ <body>
+ <div id="page-wrapper">
+ <div id="header" role="banner">
+ <header class="banner">
+ <div id="banner-text">
+ <span class="banner-title"><a href="/">beauhilton</a></span>
+ </div>
+ </header>
+ <nav>
+ <a href="/about">about</a>
+<a class="nav-active" href="/now">now</a>
+<a href="/posts">posts</a>
+<a href="https://notes.beauhilton.com">notes</a>
+<a href="https://talks.beauhilton.com">talks</a>
+<a href="https://git.beauhilton.com">git</a>
+<a href="/contact">contact</a>
+<a href="/feed.xml">rss</a>
+ </nav>
+ </div>
+ <main>
+ <h1>
+ family
+ </h1>
+ <p>
+ Our oldest is 8, youngest is 2. Everyone remains well and
+cantankerous.
+ </p>
+ <h1>
+ work
+ </h1>
+ <p>
+ I’m an internal medicine doctor at Vanderbilt University Medical
+Center.
+ </p>
+ <p>
+ In July I’ll start cancer fellowship, here as well, as a member of
+the <a href="https://medicine.vumc.org/harrison-society">Harrison
+Society</a>.
+ </p>
+ <h1>
+ other
+ </h1>
+ <p>
+ Ted Hawkins’ song “<a href="https://youtu.be/jTO-zb6XTzg">Sorry
+You’re Sick</a>” reminds me of the book <a href="https://en.wikipedia.org/wiki/One_Day_in_the_Life_of_Ivan_Denisovich"><em>One
+Day in the Life of Ivan Denisovich</em></a> by Aleksandr Solzhenitsyn,
+and the uncomfortable and sublime truth that all medicine is palliative
+medicine.
+ </p>
+ <hr>
+ <p>
+ This <a href="https://nownownow.com/about">now page</a> was last
+updated 2022-04-22.
+ </p>
+ </main>
+ <div id="footnotes"></div>
+ <footer></footer>
+ </div>
+ </body>
+</html>
diff --git a/test/posts/employee-wifi/index.html b/test/posts/employee-wifi/index.html
@@ -0,0 +1,240 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <link rel="stylesheet" href="/style.css" type="text/css">
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" type="text/css" href="/style.css">
+ <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E">
+ <title></title>
+ </head>
+ <body>
+ <div id="page-wrapper">
+ <div id="header" role="banner">
+ <header class="banner">
+ <div id="banner-text">
+ <span class="banner-title"><a href="/">beauhilton</a></span>
+ </div>
+ </header>
+ <nav>
+ <a href="/about">about</a>
+<a href="/now">now</a>
+<a class="nav-active" href="/posts">posts</a>
+<a href="https://notes.beauhilton.com">notes</a>
+<a href="https://talks.beauhilton.com">talks</a>
+<a href="https://git.beauhilton.com">git</a>
+<a href="/contact">contact</a>
+<a href="/feed.xml">rss</a>
+ </nav>
+ </div>
+ <main>
+ <h1>
+ Set Up Enterprise Wifi on Arch Linux
+ </h1>
+ <p>
+ <time id="post-date">2021-09-17</time>
+ </p>
+ <p id="post-excerpt">
+ Most big institutions have guest and employee wifi networks.
+Guest wifi is usually fine, fast enough for the basics,
+but far inferior to employee wifi.
+On a custom-built OS, such as a fairly minimalist Linux distribution,
+getting the employee wifi to work
+can be a beast.
+ </p>
+ <p>
+ This was a little tricky to get working but very worth it, so here’s
+an outline, mostly for my own later benefit.
+ </p>
+ <p></p>
+ <p>
+ This post is specific to <a href="https://www.vumc.org">VUMC</a>,
+with the VUMCEmployee network.
+ </p>
+ <p>
+ Similar steps should be applicable for other enterprise wifi users,
+though this post will unquestionably be out of date before long, and the
+intricacies of enterprise wifi are infinite.
+ </p>
+ <h2>
+ VUMCGuest is fine
+ </h2>
+ <p>
+ As with other public networks at large institutions, VUMCGuest is
+just a little slow and finicky, and it’s annoying to have to
+re-authenticate repeatedly to use all the HIPAA-compliant things.
+ </p>
+ <h2>
+ VUMCEmployee is better
+ </h2>
+ <p>
+ I’ll probably put a screenshot here at some point comparing speedtest
+scores. VUMCEmployee gives over 100 Mbps down, and around 100 up.
+ </p>
+ <p>
+ It’s also more stable, and latency is around 10ms.
+ </p>
+ <p>
+ Most practical gain, other than faster everything: When I use
+VUMCGuest, the keyboard shortcut I use to launch and automatically login
+to Epic only works intermittently. On VUMCEmployee, it works reliably.
+No more typing! It’s faster and, again, more reliable than tapping the
+badge-readers at the VUMC workstations.
+ </p>
+ <h2>
+ Backend
+ </h2>
+ <p>
+ The personal networking stack of greatest beauty on Linux at this
+point is:
+ </p>
+ <p>
+ <code>systemd-networkd</code> +<code>systemd-resolved</code> +
+<code>iwd</code>
+ </p>
+ <p>
+ Disable and delete <code>NetworkManager</code> and other such
+nonsense, if you are unwise like me and installed conflicting and
+useless things.
+ </p>
+ <p>
+ If you’d like a GUI, <a href="https://github.com/J-Lentz/iwgtk">iwgtk</a> is nice, but the CLI
+shipped with <code>iwd</code> (<code>iwctl</code>) is intuitive,
+friendly, and well-documented. I keep the GUI version around for quickly
+checking on things via a keyboard shortcut, but use the CLI for any
+heavy lifting, which has thankfully become rare since landing on this
+setup.
+ </p>
+ <h2>
+ Start with VUMCEmployeeSetup
+ </h2>
+ <p>
+ First, log on to the VUMCEmployeeSetup wifi. Then navigate to one of
+my favorite websites, <a href="http://neverssl.com/">http://neverssl.com/</a>. This will force
+the redirect to the VUMCEmployee enrollment page (I also use this site
+for connecting to public wifi at airports, libraries, coffee shops,
+etc.). Agree to the terms and conditions. Then click the “Show all
+operating systems” link at the bottom, followed by the “Other Operating
+Systems” tab that pops up at the bottom of the list.
+ </p>
+ <p>
+ The “Other Operating Systems” tab has three steps listed, which are
+simply the pieces that the various installers put together for you. The
+first two are downloads for certificates, and the third is a
+template.
+ </p>
+ <p>
+ Finding this tab was the gold mine - initially I repackaged one of
+the other Linux installers for Arch, because I thought that (since there
+was an installer) the process must be complicated, and repackaging
+things from Debian-based systems for Arch-based systems is easy enough.
+The repackaged version of the installer was decent at first, but it
+turns out that the manual process is easier and more reliable. I also
+learned more about enterprise networks in the process, which was an
+added bonus (I’m honestly not sure about the sarcasm:sincerity ratio in
+the previous sentence).
+ </p>
+ <p>
+ Download the <code>PEM</code> files listed under Steps 1 (root
+certificate) and 2 (client certificate).
+ </p>
+ <h2>
+ Make your own <code>iwd</code> profile
+ </h2>
+ <p>
+ Here’s where it goes:
+<code>/var/lib/iwd/VUMCEmployee.8021x</code>
+ </p>
+ <p>
+ Below are the contents, sensitive info redacted, then we’ll go
+through some of the key parts and one nicety.
+ </p>
+ <pre tabindex="0"><code class="language-toml"><span class="hl kwa">[IPv6]</span>
+<span class="hl kwb">Enabled</span><span class="hl opt">=</span><span class="hl kwd">true</span>
+
+<span class="hl kwa">[Security]</span>
+<span class="hl kwb">EAP-Method</span><span class="hl opt">=</span>PEAP
+<span class="hl kwb">EAP-Identity</span><span class="hl opt">=</span>username
+<span class="hl kwb">EAP-PEAP-CACert</span><span class="hl opt">=</span>embed<span class="hl opt">:</span>root_cert
+<span class="hl kwb">EAP-PEAP-ServerDomainMask</span><span class="hl opt">=*</span>.radius.service.vumc.org
+<span class="hl kwb">EAP-PEAP-Phase2-Method</span><span class="hl opt">=</span>MSCHAPV2
+<span class="hl kwb">EAP-PEAP-Phase2-Identity</span><span class="hl opt">=</span>username
+<span class="hl kwb">EAP-PEAP-Phase2-Password</span><span class="hl opt">=</span>password
+
+<span class="hl kwa">[Settings]</span>
+<span class="hl kwb">AutoConnect</span><span class="hl opt">=</span><span class="hl kwd">true</span>
+
+<span class="hl kwa">[@pem@root_cert]</span>
+<span class="hl opt">-----</span>BEGIN CERTIFICATE<span class="hl opt">-----</span>
+<span class="hl opt">*</span>lots of gobbledigook goes here<span class="hl opt">*</span>
+<span class="hl opt">-----</span>END CERTIFICATE<span class="hl opt">-----</span>
+</code></pre>
+ <p>
+ Most of these options are outlined in Step 3 from the
+VUMCEmployeeSetup, cross-referenced against the Arch Wiki page on
+<code>iwd</code>, subsection <a href="https://wiki.archlinux.org/title/Iwd#EAP-PEAP">Network
+configuration</a>, and the <a href="https://iwd.wiki.kernel.org/networkconfigurationsettings"><code>iwd</code>
+wiki proper</a>.
+ </p>
+ <p>
+ An easy-to-miss step: The <code>EAP-PEAP-Phase2-Method</code>
+requirement for <code>MSCHAPV2</code> leads to another required install,
+check the wiki for current instructions.
+ </p>
+ <p>
+ Put in your own username and password.
+ </p>
+ <p>
+ My favorite trick in this file is directly embedding the root
+certificate in the line <code>EAP-PEAP-CACert=</code> with the syntax
+<code>embed:root_cert</code> (any name is fine, doesn’t have to be
+<code>root_cert</code>, it’s just a pointer). Then you add a definition
+of <code>root_cert</code> in a <code>[@pem@root_cert]</code> section.
+Insert the contents of the root certificate directly via copy-paste or
+<code>cat</code>, etc.
+ </p>
+ <p>
+ Easiest method, as root:
+ </p>
+ <pre tabindex="0"><code class="language-shell">cat /home/beau/dl/root_cert.PEM >> /var/lib/iwd/VUMCEmployee.8021x
+</code></pre>
+ <p>
+ With the direct embed method, you don’t need to point to the root
+certificate file or keep it around at all.
+ </p>
+ <p>
+ Needless to say, <code>VUMCEmployee.8021x</code> is a sensitive file
+and should be protected appropriately. However, this file or a version
+of it is what the automated tools would have made anyway, so there’s no
+special risk here - AND since you did it all yourself you know there was
+no funny business coming from a black-box installer.
+ </p>
+ <h2>
+ The other certificate (Client)
+ </h2>
+ <p>
+ I can’t remember what I had to do with the client cert, probably
+added using the Chrome/Firefox certificate managers.
+ </p>
+ <p>
+ I had to do this before when getting set up for VA remote access, the
+Arch Wiki comes through again with an article on <a href="https://wiki.archlinux.org/title/Common_Access_Card">Common Access
+Cards</a> that includes instructions on adding certs to browsers.
+ </p>
+ <p>
+ There’s a chance it’s not even needed? The <a href="https://iwd.wiki.kernel.org/networkconfigurationsettings">specification</a>
+no longer supports adding a client cert field without a key, which I
+don’t have, and do not, apparently, need (see the section “EAP-PEAP with
+tunneled EAP-MSCHAPV2”). At any rate, this setup is working now and I
+won’t futz with it further until something breaks.
+ </p>
+ <h2>
+ -> ~~Profit~~ Prosper
+ </h2>
+ </main>
+ <div id="footnotes"></div>
+ <footer></footer>
+ </div>
+ </body>
+</html>
diff --git a/test/posts/geocheatcode/index.html b/test/posts/geocheatcode/index.html
@@ -0,0 +1,243 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <link rel="stylesheet" href="/style.css" type="text/css">
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" type="text/css" href="/style.css">
+ <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E">
+ <title></title>
+ </head>
+ <body>
+ <div id="page-wrapper">
+ <div id="header" role="banner">
+ <header class="banner">
+ <div id="banner-text">
+ <span class="banner-title"><a href="/">beauhilton</a></span>
+ </div>
+ </header>
+ <nav>
+ <a href="/about">about</a>
+<a href="/now">now</a>
+<a class="nav-active" href="/posts">posts</a>
+<a href="https://notes.beauhilton.com">notes</a>
+<a href="https://talks.beauhilton.com">talks</a>
+<a href="https://git.beauhilton.com">git</a>
+<a href="/contact">contact</a>
+<a href="/feed.xml">rss</a>
+ </nav>
+ </div>
+ <main>
+ <h1>
+ geocheatcode
+ </h1>
+ <p>
+ <time id="post-date">2022-04-22</time>
+ </p>
+ <p id="post-excerpt">
+ Here is background and code
+for a trick I use to get
+Google to give me best-in-class guesses
+for latitude and longitude,
+despite goofy and/or downright bad location searches.
+ </p>
+ <h2>
+ Map all the things
+ </h2>
+ <p>
+ I love maps.
+ </p>
+ <p>
+ Several of my projects involve mapping things at scale.
+ </p>
+ <p>
+ When you want to map a few things, you type searches into Google Maps
+and get addresses and/or latitudes and longitudes quickly and
+reliably.
+ </p>
+ <p>
+ But what if you’d like to map 90,000 things whose locations you don’t
+yet know?
+ </p>
+ <p>
+ <a href="https://developers.google.com/maps">Google</a> and <a href="https://www.openstreetmap.org/">OpenStreetMap</a>, as well as
+others, provide mapping services you can call programmatically from your
+software. You send in some query, such as “VUMC Internal Medicine,” and
+they return information relevant to that query, such as street address
+and latitude and longitude. Up to a certain number of queries per day or
+hour, the services are free, and since my work is academic, rather than
+real-time mapping for some for-profit app, I am happy to send in small
+batches to stay under the limits in the free tier.
+ </p>
+ <p>
+ I’ve used these services to make large maps, and they work pretty
+well.
+ </p>
+ <p>
+ <em>Pretty</em> well.
+ </p>
+ <h2>
+ But mapping is hard
+ </h2>
+ <p>
+ Problems with these services:
+ </p>
+ <ol type="1">
+ <li>
+ they expected well-formed and reasonable queries
+ </li>
+ <li>
+ if they didn’t know the answer, the guesses were often wildly off,
+or they would refuse to guess at all
+ </li>
+ </ol>
+ <p>
+ If I’m mapping 90,000 things, I’m going to write some code to go
+through each of those 90,000 things and ask the mapping services to
+kindly tell me what I want to know. Though I write sanitation code to
+clean up the 90,000 things, I’m not going to quality check each of those
+90,000 things. Sometimes things among the 90,000 things are kinda nuts
+(misspelled, inclusive of extraneous data, oddly formatted), in
+idiosyncratic ways that are impossible to completely cover, no matter
+how much code I write to catch the weird cases.
+ </p>
+ <p>
+ I would like a solution that is fairly tolerant of weirdnesses, and
+makes good guesses.
+ </p>
+ <h2>
+ Google is really good at search
+ </h2>
+ <p>
+ I noticed that when I manually typed things into the Google Maps
+search bar, it forgave a myriad of sins and did a great job centering
+the map on its best guess. When I copied and pasted some of the weird
+things among the 90,000 into the Google Maps search bar (the same things
+that made the official mapping services - including Google’s - go all
+Poltergeist), <em>voila!</em>, the right answer appeared, success rates
+nearing 100%.
+ </p>
+ <p>
+ I thought there must be a way to repeat this process with code, in a
+scalable way.
+ </p>
+ <p>
+ Turns out there is, and it’s easy.
+ </p>
+ <h2>
+ <code>geocheatcode.py</code>
+ </h2>
+ <pre tabindex="0"><code class="language-python">
+<span class="hl kwa">from</span> requests_html <span class="hl kwa">import</span> HTMLSession
+
+session <span class="hl opt">=</span> <span class="hl kwd">HTMLSession</span><span class="hl opt">()</span>
+
+
+<span class="hl kwa">def</span> <span class="hl kwd">google_lat_lon</span><span class="hl opt">(</span>query<span class="hl opt">:</span> <span class="hl kwb">str</span><span class="hl opt">):</span>
+
+ url <span class="hl opt">=</span> <span class="hl sng">"https://www.google.com/maps/search/?api=1"</span>
+ params <span class="hl opt">= {}</span>
+ params<span class="hl opt">[</span><span class="hl sng">"query"</span><span class="hl opt">] =</span> query
+
+ r <span class="hl opt">=</span> session<span class="hl opt">.</span><span class="hl kwd">get</span><span class="hl opt">(</span>url<span class="hl opt">,</span> params<span class="hl opt">=</span>params<span class="hl opt">)</span>
+
+ reg <span class="hl opt">=</span> <span class="hl sng">"APP_INITIALIZATION_STATE=[[[{}]"</span>
+ res <span class="hl opt">=</span> r<span class="hl opt">.</span>html<span class="hl opt">.</span><span class="hl kwd">search</span><span class="hl opt">(</span>reg<span class="hl opt">)[</span><span class="hl num">0</span><span class="hl opt">]</span>
+ lat <span class="hl opt">=</span> res<span class="hl opt">.</span><span class="hl kwd">split</span><span class="hl opt">(</span><span class="hl sng">","</span><span class="hl opt">)[</span><span class="hl num">2</span><span class="hl opt">]</span>
+ lon <span class="hl opt">=</span> res<span class="hl opt">.</span><span class="hl kwd">split</span><span class="hl opt">(</span><span class="hl sng">","</span><span class="hl opt">)[</span><span class="hl num">1</span><span class="hl opt">]</span>
+
+ <span class="hl kwa">return</span> lat<span class="hl opt">,</span> lon
+
+
+extraneous <span class="hl opt">=</span> <span class="hl sng">""" something something</span>
+<span class="hl sng"> the earth is banana shaped</span>
+<span class="hl sng"> latitude and longitude </span>
+<span class="hl sng"> wouldn't you like to know, maybe """</span>
+
+relevant <span class="hl opt">=</span> <span class="hl sng">""" Vanderbilt University Medical Center </span>
+<span class="hl sng"> Internal Medicine """</span>
+
+query <span class="hl opt">=</span> extraneous <span class="hl opt">+</span> relevant
+
+lat<span class="hl opt">,</span> lon <span class="hl opt">=</span> <span class="hl kwd">google_lat_lon</span><span class="hl opt">(</span>query<span class="hl opt">)</span>
+
+<span class="hl kwa">print</span><span class="hl opt">(</span>
+ <span class="hl sng">"Hello. "</span>
+ <span class="hl sng">"My name is Google. "</span>
+ <span class="hl sng">"I am really good at guessing what you meant. "</span>
+ f<span class="hl sng">"Your query was '</span><span class="hl ipl">{query}</span><span class="hl sng">'. "</span>
+ <span class="hl sng">"Here are the coordinates you probably wanted. "</span>
+ f<span class="hl sng">"The latitude is</span> <span class="hl ipl">{lat}</span><span class="hl sng">, and the longitude is</span> <span class="hl ipl">{lon}</span><span class="hl sng">. "</span>
+ <span class="hl sng">"Don't believe me? "</span>
+ <span class="hl sng">"Here it is again, "</span>
+ <span class="hl sng">"in a format you can paste into the search bar:</span> <span class="hl esc">\n</span><span class="hl sng">"</span>
+ f<span class="hl sng">"</span><span class="hl ipl">{lat}</span><span class="hl sng">,</span> <span class="hl ipl">{lon}</span> <span class="hl sng"></span><span class="hl esc">\n</span><span class="hl sng">"</span>
+ <span class="hl sng">"Told ya. "</span>
+<span class="hl opt">)</span>
+</code></pre>
+ <p>
+ Despite having all that extra junk in the query, this returns the
+right answer. Because Google is many things good and evil, but of these
+one is certain: Google is <em>really</em> good at search.
+ </p>
+ <h2>
+ How does the code work?
+ </h2>
+ <p>
+ If you inspect the source HTML on the Google Maps website after you
+search for something and it centers the map on its best guess, and you
+scroll way on down (or Ctrl-F search for it) you’ll find
+<code>APP_INITIALIZATION_STATE</code>, which contains latitude and
+longitude for the place the map centered on.
+ </p>
+ <ul>
+ <li>
+ <a href="https://www.google.com/maps?q=something+whose+latitude+and+longitude+you+would+like+to+know,+maybe+VUMC+Internal+Medicine">example
+search</a>
+ </li>
+ <li>
+ <a href="view-source:https://www.google.com/maps/search/something+whose+latitude+and+longitude+you+would+like+to+know,+maybe+VUMC+Internal+Medicine/">example
+source</a> (you have to copy and paste this link into a new tab
+manually, clicking won’t work)
+ </li>
+ </ul>
+ <p>
+ I use the lovely <a href="https://docs.python-requests.org/projects/requests-html/en/latest/"><code>requests-html</code></a>
+Python library to send the query to Google, receive the response, and
+search through the response for the part I want to extract. Then I use a
+little standard Python to parse the extracted part and save the
+important bits.
+ </p>
+ <h2>
+ With great power…
+ </h2>
+ <p>
+ Don’t go crazy with this.
+ </p>
+ <p>
+ The trick is good for leisurely automation of location retrieval when
+you have squirrelly queries.
+ </p>
+ <p>
+ If you need real-time mapping of many things, you don’t want this
+solution. Use the actual APIs, and work instead on formatting the
+queries properly before sending them to Google/OSM.
+ </p>
+ <p>
+ Also, if you try to query too much/too quickly, Google will shut you
+out after a little while. Put a few seconds of delay between each
+request and run it overnight and/or in automated batches.
+ </p>
+ <h2>
+ Know a better way?
+ </h2>
+ <p>
+ I’d love to know. Drop me a line.
+ </p>
+ </main>
+ <div id="footnotes"></div>
+ <footer></footer>
+ </div>
+ </body>
+</html>
diff --git a/test/posts/index.html b/test/posts/index.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <link rel="stylesheet" href="/style.css" type="text/css">
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" type="text/css" href="/style.css">
+ <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E">
+ <title></title>
+ </head>
+ <body>
+ <div id="page-wrapper">
+ <div id="header" role="banner">
+ <header class="banner">
+ <div id="banner-text">
+ <span class="banner-title"><a href="/">beauhilton</a></span>
+ </div>
+ </header>
+ <nav>
+ <a href="/about">about</a>
+<a href="/now">now</a>
+<a class="nav-active" href="/posts">posts</a>
+<a href="https://notes.beauhilton.com">notes</a>
+<a href="https://talks.beauhilton.com">talks</a>
+<a href="https://git.beauhilton.com">git</a>
+<a href="/contact">contact</a>
+<a href="/feed.xml">rss</a>
+ </nav>
+ </div>
+ <main>
+ <h1 id="title">
+ Posts
+ </h1>
+ <p>
+ You can subscribe to the <a href="/atom.xml">Atom feed</a> to receive updates.
+ </p>
+ <div id="posts-index">
+ <h2>
+ <a href="/posts/mime">fix MIME Types to unbreak RSS feeds served by OpenBSD’s
+httpd(8)</a>
+ </h2>
+ <p>
+ <strong>Last update:</strong> 2022-11-13.
+ </p>
+ <p>
+ I've been getting back into RSS lately.
+Turns out, my own RSS feed was broken.
+ </p>
+ <a href="/posts/mime">Read more</a>
+ <h2>
+ <a href="/posts/ugbsd">Upgrading out-of-date OpenBSD installs</a>
+ </h2>
+ <p>
+ <strong>Last update:</strong> 2022-11-11.
+ </p>
+ <p>
+ First of all, don't do how I do.
+Upgrade your installs regularly.
+OpenBSD makes it very easy.
+ </p>
+ <a href="/posts/ugbsd">Read more</a>
+ <h2>
+ <a href="/posts/geocheatcode">geocheatcode</a>
+ </h2>
+ <p>
+ <strong>Last update:</strong> 2022-04-22.
+ </p>
+ <p>
+ Here is background and code
+for a trick I use to get
+Google to give me best-in-class guesses
+for latitude and longitude,
+despite goofy and/or downright bad location searches.
+ </p>
+ <a href="/posts/geocheatcode">Read more</a>
+ <h2>
+ <a href="/posts/intake-2022-03-25">intake</a>
+ </h2>
+ <p>
+ <strong>Last update:</strong> 2022-03-25.
+ </p>
+ <p>
+ candidal esophagitis, achalasia, H Pylori PUD
+ </p>
+ <a href="/posts/intake-2022-03-25">Read more</a>
+ <h2>
+ <a href="/posts/employee-wifi">Set Up Enterprise Wifi on Arch Linux</a>
+ </h2>
+ <p>
+ <strong>Last update:</strong> 2021-09-17.
+ </p>
+ <p>
+ Most big institutions have guest and employee wifi networks.
+Guest wifi is usually fine, fast enough for the basics,
+but far inferior to employee wifi.
+On a custom-built OS, such as a fairly minimalist Linux distribution,
+getting the employee wifi to work
+can be a beast.
+ </p>
+ <a href="/posts/employee-wifi">Read more</a>
+ <h2>
+ <a href="/posts/mr-2021">Morning Report 08/23/2021</a>
+ </h2>
+ <p>
+ <strong>Last update:</strong> 2021-08-23.
+ </p>
+ <p>
+ Diagnosis is... MDS/MPN/MF NOS.
+i.e., who knows.
+ </p>
+ <a href="/posts/mr-2021">Read more</a>
+ </div>
+ </main>
+ <div id="footnotes"></div>
+ <footer></footer>
+ </div>
+ </body>
+</html>
diff --git a/test/posts/intake-2022-03-25/index.html b/test/posts/intake-2022-03-25/index.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <link rel="stylesheet" href="/style.css" type="text/css">
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" type="text/css" href="/style.css">
+ <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E">
+ <title></title>
+ </head>
+ <body>
+ <div id="page-wrapper">
+ <div id="header" role="banner">
+ <header class="banner">
+ <div id="banner-text">
+ <span class="banner-title"><a href="/">beauhilton</a></span>
+ </div>
+ </header>
+ <nav>
+ <a href="/about">about</a>
+<a href="/now">now</a>
+<a class="nav-active" href="/posts">posts</a>
+<a href="https://notes.beauhilton.com">notes</a>
+<a href="https://talks.beauhilton.com">talks</a>
+<a href="https://git.beauhilton.com">git</a>
+<a href="/contact">contact</a>
+<a href="/feed.xml">rss</a>
+ </nav>
+ </div>
+ <main>
+ <h1>
+ intake
+ </h1>
+ <p>
+ <time id="post-date">2022-03-25</time>
+ </p>
+ <h2>
+ cc: trouble swallowing and weight loss
+ </h2>
+ <p>
+ 28M w few weeks of trouble swallowing (gets stuck “right here,”
+points to mid-sternum), solid/liquids same, gradual over months-weeks,
+some vomiting w/o specific timing. Sometimes has pain when not eating.
+20lb weight loss over months. No skin lesions. ?thrush.
+ </p>
+ <h2>
+ PMHx/PSHx
+ </h2>
+ <p>
+ dx BPD, no other dx or procedures
+ </p>
+ <h2>
+ SHx
+ </h2>
+ <ul>
+ <li>
+ MSM w occasional use of protection, no PrEP
+ </li>
+ <li>
+ occ MJ use, no other substances
+ </li>
+ <li>
+ unemployed, lives w mom
+ </li>
+ <li>
+ no unusual hobbies or travel
+ </li>
+ </ul>
+ <h2>
+ PE
+ </h2>
+ <p>
+ HR 100, SBP 80 -> 100 w 500mL LR, AF cachectic (temporal,
+hypothenar wasting) +skin tenting diffuse abd tenderness
+ </p>
+ <h2>
+ w/u
+ </h2>
+ <p>
+ Hgb 10, MCV 88, WBC ~4, ANC 1500 BMP wnl Alb 3.4 HIV+, VL 15k, rest
+of STI -ve
+ </p>
+ <p>
+ CXR wnl (AP and lateral)
+ </p>
+ <h2>
+ dx
+ </h2>
+ <p id="post-excerpt">
+ candidal esophagitis, achalasia, H Pylori PUD
+ </p>
+ </main>
+ <div id="footnotes"></div>
+ <footer></footer>
+ </div>
+ </body>
+</html>
diff --git a/test/posts/mime/index.html b/test/posts/mime/index.html
@@ -0,0 +1,144 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <link rel="stylesheet" href="/style.css" type="text/css">
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" type="text/css" href="/style.css">
+ <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E">
+ <title></title>
+ </head>
+ <body>
+ <div id="page-wrapper">
+ <div id="header" role="banner">
+ <header class="banner">
+ <div id="banner-text">
+ <span class="banner-title"><a href="/">beauhilton</a></span>
+ </div>
+ </header>
+ <nav>
+ <a href="/about">about</a>
+<a href="/now">now</a>
+<a class="nav-active" href="/posts">posts</a>
+<a href="https://notes.beauhilton.com">notes</a>
+<a href="https://talks.beauhilton.com">talks</a>
+<a href="https://git.beauhilton.com">git</a>
+<a href="/contact">contact</a>
+<a href="/feed.xml">rss</a>
+ </nav>
+ </div>
+ <main>
+ <h1>
+ fix MIME Types to unbreak RSS feeds served by OpenBSD’s
+httpd(8)
+ </h1>
+ <p>
+ <time id="post-date">2022-11-13</time>
+ </p>
+ <h2>
+ RSS is life - but mine was broken
+ </h2>
+ <p>
+ As of today (2022-11-13) my website lives on an OpenBSD server hosted
+at <a href="https://vultr.com">vultr</a>.
+ </p>
+ <p>
+ It’s great, delightfully simple and low-resource, robust, extendable,
+low-maintenance.
+ </p>
+ <p id="post-excerpt">
+ I've been getting back into RSS lately.
+Turns out, my own RSS feed was broken.
+ </p>
+ <p>
+ I knew it was janky, but would have had no idea how broken it was if
+not for the great folks on the <a href="https://datasette.io">datasette</a> Discord, one of whom reached
+out to let me know my RSS link wasn’t working.
+ </p>
+ <p>
+ This could not stand!
+ </p>
+ <p>
+ I’ve been meaning to fix my RSS feed anyway, and now I had a good
+reason.
+ </p>
+ <h2>
+ fixing the file itself
+ </h2>
+ <p>
+ I ended up tearing out my previous RSS solution, <a href="https://romanzolotarev.com/rssg.html"><code>rssg</code></a>, which
+is great but made some assumptions about my site’s layout that aren’t
+true. I could have rewritten the script, but I’m lazy and a little
+strapped for time, so I ended up replacing it with a hand-written RSS
+file.
+ </p>
+ <p>
+ (The RSS spec is easy enough to write by hand, a little copy-paste
+and replace to add a new article - at some point I’ll probably migrate
+to <code>hugo</code> or similar and hand off the feed creation to a more
+flexible script, but for now this works).
+ </p>
+ <p>
+ After I was certain the file format was fine and had the info I
+wanted, I thought I was good.
+ </p>
+ <h2>
+ fixing the MIME Type
+ </h2>
+ <p>
+ The kind soul who reached out to let me know the RSS feed was
+malformed reached out again to let me know he was now getting a MIME
+Type error.
+ </p>
+ <p>
+ My feedreader of choice, <code>newsboat</code>, is very forgiving of
+what it accepts, and didn’t throw any errors when I tested it.
+<code>FreshRSS</code>, on the other hand, is more strict, and the feed
+would fail even though the file itself was fine.
+ </p>
+ <p>
+ I looked into it, and found out that <code>httpd(8)</code> only
+supports a handful of MIME Types by default, so my server was sending
+out <code>application/octet-stream</code> (a generic type) instead of
+the <code>rss+xml</code> type, and it was confusing the feedreader.
+ </p>
+ <h2>
+ add all the types
+ </h2>
+ <p>
+ Thank goodness, and as usual in OpenBSD, there’s a very easy way to
+add all the relevant types one might need.
+ </p>
+ <p>
+ OpenBSD has an internal MIME declaration file you can link to from
+within <code>httpd.conf(5)</code>.
+ </p>
+ <p>
+ Here’s the relevant bit, just chuck this on the end of the conf
+file:
+ </p>
+ <pre tabindex="0"><code class="language-shell">
+types {
+ include "/usr/share/misc/mime.types"
+}
+</code></pre>
+ <p>
+ And reload <code>httpd(8)</code>.
+ </p>
+ <h2>
+ great success
+ </h2>
+ <p>
+ Much thanks to my new friend on the Datasette Discord, the fantastic
+OpenBSD documentation, as always, and <a href="https://blog.lambda.cx/posts/openbsd-httpd-mime-types/">lambda.cx</a>
+for writing a post almost identical to mine (except that his had nothing
+to do with RSS - he was fixing PDF serving, which should now be fixed on
+my site as well).
+ </p>
+ </main>
+ <div id="footnotes"></div>
+ <footer></footer>
+ </div>
+ </body>
+</html>
diff --git a/test/posts/mr-2021/index.html b/test/posts/mr-2021/index.html
@@ -0,0 +1,419 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <link rel="stylesheet" href="/style.css" type="text/css">
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" type="text/css" href="/style.css">
+ <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E">
+ <title></title>
+ </head>
+ <body>
+ <div id="page-wrapper">
+ <div id="header" role="banner">
+ <header class="banner">
+ <div id="banner-text">
+ <span class="banner-title"><a href="/">beauhilton</a></span>
+ </div>
+ </header>
+ <nav>
+ <a href="/about">about</a>
+<a href="/now">now</a>
+<a class="nav-active" href="/posts">posts</a>
+<a href="https://notes.beauhilton.com">notes</a>
+<a href="https://talks.beauhilton.com">talks</a>
+<a href="https://git.beauhilton.com">git</a>
+<a href="/contact">contact</a>
+<a href="/feed.xml">rss</a>
+ </nav>
+ </div>
+ <main>
+ <h1>
+ Morning Report 08/23/2021
+ </h1>
+ <p>
+ <time id="post-date">2021-08-23</time>
+ </p>
+ <p>
+ Details modified, generalized, and otherwise fudged to be
+HIPAA-compliant.
+ </p>
+ <h2>
+ HPI
+ </h2>
+ <p>
+ 72F with chest pain, abdominal pain, and constipation.
+ </p>
+ <p>
+ 2-3mo weight loss, night sweats.
+ </p>
+ <p>
+ 2-3wk +perineal ?cyst, initially ttp and hurt to walk, but now
+nontender.
+ </p>
+ <p>
+ ~1wk constipation, BRB on TP.
+ </p>
+ <p>
+ +crampy LLQ pain 8/10, x3-4 days, improves with positioning (supine
+with head raised somewhat, 3-4 pillows).
+ </p>
+ <p>
+ +LUQ and left-sided chest pain x1-2 days, radiates to L arm, not
+related to exertion, lasts a few minutes.
+ </p>
+ <h2>
+ OP Meds
+ </h2>
+ <ul>
+ <li>
+ duloxetine 60mg
+ </li>
+ <li>
+ ASA 81mg
+ </li>
+ <li>
+ melatonin 6mg
+ </li>
+ <li>
+ no notable allergies
+ </li>
+ </ul>
+ <h2>
+ PMSHx
+ </h2>
+ <ul>
+ <li>
+ TVH-BSO for fibroids and endometriosis (~20y ago)
+ </li>
+ <li>
+ hemorrhoids (no surgeries)
+ </li>
+ <li>
+ s/p Moderna COVID vaccine (~4wk ago)
+ </li>
+ <li>
+ UTD on mammograms, colonoscopies, no deviations from regular
+schedule
+ </li>
+ </ul>
+ <h2>
+ SHx
+ </h2>
+ <ul>
+ <li>
+ monogamous x45y, G2P2 sons, 6yo grandson, all healthy
+ </li>
+ <li>
+ never smoker
+ </li>
+ <li>
+ social EtOH, none this year
+ </li>
+ <li>
+ no non-Rx medicines
+ </li>
+ <li>
+ previously secretary
+ </li>
+ <li>
+ likes to DIY: painting, home crafts, gardening
+ </li>
+ </ul>
+ <h2>
+ FHx
+ </h2>
+ <ul>
+ <li>
+ M GM: uterine cancer (~40yo)
+ </li>
+ <li>
+ P GF: lung ca, unknown type (~70yo)
+ </li>
+ </ul>
+ <h2>
+ PE
+ </h2>
+ <ul>
+ <li>
+ VS: wnl
+ </li>
+ <li>
+ GEN: NAD
+ </li>
+ <li>
+ HEENT: no LAD
+ </li>
+ <li>
+ PULM: fine
+ </li>
+ <li>
+ CV: fine
+ </li>
+ <li>
+ ABD: NTND, +splenomegaly
+ </li>
+ <li>
+ GYN: 0.5cm lesion R side of anterior perineum, NT, freely
+mobile
+ </li>
+ <li>
+ NEURO: fine
+ </li>
+ </ul>
+ <h2>
+ Labs
+ </h2>
+ <ul>
+ <li>
+ Hgb 12.7
+ </li>
+ <li>
+ WBC 58.3
+ <ul>
+ <li>
+ 0 blasts
+ </li>
+ <li>
+ 0 atypical lymphs
+ </li>
+ <li>
+ <ul>
+ <li>
+ slight L shift
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li>
+ Plt 490
+ </li>
+ <li>
+ BMP grossly wnl (gluc 202, <a href="https://www.ashclinicalnews.org/viewpoints/editors-corner/illegitimi-epic-non-carborundum-dont-let-epic-bastards-grind/">Cr
+fine</a>)
+ </li>
+ <li>
+ LFTs fine
+ </li>
+ <li>
+ Trop <0.01
+ </li>
+ <li>
+ urate 10.4
+ </li>
+ <li>
+ phos 5.0
+ </li>
+ <li>
+ LDH 330
+ </li>
+ <li>
+ fibrinogen 355
+ </li>
+ </ul>
+ <h2>
+ Other studies
+ </h2>
+ <ul>
+ <li>
+ EKG wnl
+ </li>
+ <li>
+ CT-PE -ve
+ </li>
+ <li>
+ CT a/p wwo
+ <ul>
+ <li>
+ +10x7cm pelvic mass (central/R adnexum, exerting mass effect on
+sigmoid colon)
+ </li>
+ <li>
+ spleen ~20cm largest dimension w ?infarcts x2,
+ </li>
+ <li>
+ L internal iliac vein filling defects c/w nonocclusive DVT
+ </li>
+ </ul>
+ </li>
+ <li>
+ PET/CT
+ <ul>
+ <li>
+ splenomegaly with diffusely increased uptake, diffuse FDG uptake of
+axial and appendicular skeleton, mild uptake of abdominal pelvic lymph
+nodes, and minimal to mild uptake in the pelvic mass.
+ </li>
+ </ul>
+ </li>
+ </ul>
+ <h2>
+ Further notes on hospital course
+ </h2>
+ <ul>
+ <li>
+ CEA 1.7 (wnl), CA-125 52 (-)
+ </li>
+ <li>
+ urate 9.5 5d later w IVF, given rasburicase 3mg x1 -> urate
+3.8
+ </li>
+ <li>
+ phos similarly without movement, sevelamer eventually helpful
+ </li>
+ <li>
+ pelvic mass bx: smooth muscle
+ </li>
+ <li>
+ BMBx: hypercellular >90%, no blasts, +trilineage atypica >
+myeloid, MF-1 fibrosis.
+ </li>
+ <li>
+ JAK2 -ve, BCR/ABL -ve
+ </li>
+ <li>
+ NGS
+ <ul>
+ <li>
+ BRAF 5% (MGUS, MM, hairy cell, hystiocytic/dendritic cell, solid
+tumors, therapy-related myeloid neoplasms)
+ </li>
+ <li>
+ KRAS 39% (MDS, AML, MDS/MPN inc CMML and JMML)
+ </li>
+ <li>
+ BCOR 49% (?, possibly germline since allele fraction ~50%)
+ </li>
+ <li>
+ BCORL1 48% (ditto)
+ </li>
+ <li>
+ EZH2 93% (?, likely germline w loss of heterozygosity)
+ </li>
+ </ul>
+ </li>
+ </ul>
+ <h2>
+ And then…
+ </h2>
+ <p id="post-excerpt">
+ Diagnosis is... MDS/MPN/MF NOS.
+i.e., who knows.
+ </p>
+ <p>
+ Started on hydroxyurea and decitabine, c/b recurrent bacteremia, so
+currently tx on hold.
+ </p>
+ <hr>
+ <h2>
+ TLS
+ </h2>
+ <p>
+ The big idea, and a few finer points.
+ </p>
+ <p>
+ <a href="https://jamanetwork.com/journals/jamaoncology/fullarticle/2680750">![TLS](https://cdn.jamanetwork.com/ama/content_public/journal/oncology/937239/cpg180002fa.png?Expires=1632594426&Signature=y4M-w5gXSYJCAVMqGVEyfaPaqZocE9nGaWFnmr7GY7vuiD35l7dL-yJLWn4l3huTo4yBhri1nM0KjQ4dZBBjEYH5tPmKExEJ0D6V~WNou9Av-OEwhyQh79y9feHp790YWY6hTKRJJge958meDu~OmNl8Sl0Wn1N4buZZgVNMRdRds9fKbaDr4DhEdCbMgFbbLSeW9h8KIOm49Gog8FREQNntRaN1jILZgKPBTr9sUNv2BUiapZaLPO4teIf33LkJXcStx6o1VVsZJoP-G-sfMKG3ql1O~23E6LFJeirnMt5MYQdfk-LZlieuSw16HzqTXr-jBtOicDtyFzDJ9VcQ~g__&Key-Pair-Id=APKAIE5G5CRDK6RD3PGA
+=500x500 ‘JAMA Oncology 2018, TLS Review’)</a>
+ </p>
+ <h3>
+ Cairo-Bishop classification system
+ </h3>
+ <p>
+ (Most of the following derived from <a href="https://www.asn-online.org/education/distancelearning/curricula/onco/Chapter4.pdf">Chapter
+4</a> of the American Society of Nephrology online <a href="https://www.asn-online.org/education/distancelearning/curricula/onco/">Onco-Nephrology
+curriculum</a>, which is good and great.)
+ </p>
+ <h3>
+ Laboratory TLS
+ </h3>
+ <p>
+ Definition: Chemotherapy plus the two or more of the following within
+3d before or 7d after initiation (so doesn’t account for the spontaneous
+TLS seen in our patient).
+ </p>
+ <p>
+ | Metabolite/Electrolyte | Criterion | | :———————– |
+:––––––––––––––––––––: | | Uric Acid | >=8 mg/dL or 25% increase from
+baseline | | Potassium | >=6mEq/L or 25% increase from baseline | |
+Phosphorus | >=4.5mg/dL or 25% increase from baseline | | Calcium |
+25% <em>decrease</em> from baseline |
+ </p>
+ <p>
+ The “25% increase/decrease” part is contested, as it may not be
+clinically meaningful if the value stays within the normal range.
+ </p>
+ <h3>
+ Clinical TLS
+ </h3>
+ <p>
+ | Laboratory TLS and one or more of | | :–––––––––––––––– | |
+creatinine >= 1.5 ULN (Note: just use AKI criteria) | | cardiac
+arrhythmia or sudden death | | seizure |
+ </p>
+ <ul>
+ <li>
+ risk assessment
+ </li>
+ </ul>
+ <h3>
+ Treating TLS
+ </h3>
+ <p>
+ IVF, electrolytes, rasburicase.
+ </p>
+ <p>
+ Rasburicase is the subject of a recent “Things We Do for No
+Reason.”
+ </p>
+ <p>
+ <a href="https://www.journalofhospitalmedicine.com/jhospmed/article/241443/hospital-medicine/things-we-do-no-reasontm-rasburicase-adult-patients-tumor">Pay-walled
+article</a>, <a href="https://cdn.mdedge.com/files/s3fs-public/JHM01607424.PDF">PDF made
+available by the authors</a>
+ </p>
+ <p>
+ TL;DR: the evidence is thin, but could be reasonable to
+ </p>
+ <ul>
+ <li>
+ ppx w IVF and allopurinol for low-med risk,
+ </li>
+ <li>
+ use single 3mg dose rasburicase as ppx in high-risk disease (don’t
+use weight-based dosing),
+ </li>
+ <li>
+ tx active TLS (laboratory or clinical) with aggressive fluid
+resuscitation and electrolyte mgmt, possibly single 3mg dose.
+ </li>
+ </ul>
+ <p>
+ Hard outcomes in support of rasburicase are generally lacking, e.g.
+consistently reducing renal injury, renal failure, length of stay.
+ </p>
+ <p>
+ It also seems like the classification criteria need revamping, with a
+larger N. It’s been a while. However, like redefining fever, it’s
+difficult to get a clean slate, because we act on the established
+criteria so aggressively.
+ </p>
+ <hr>
+ <h2>
+ MDS/MPN overlap syndromes
+ </h2>
+ <p>
+ Not much to say here, except that the dx is not always clear-cut,
+even with BMBx and NGS data, so the clinical picture matters, and
+sometimes we have to shoot in the dark.
+ </p>
+ <hr>
+ <p>
+ Last updated: 2021-08-22
+ </p>
+ </main>
+ <div id="footnotes"></div>
+ <footer></footer>
+ </div>
+ </body>
+</html>
diff --git a/test/posts/ugbsd/index.html b/test/posts/ugbsd/index.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <link rel="stylesheet" href="/style.css" type="text/css">
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" type="text/css" href="/style.css">
+ <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E">
+ <title></title>
+ </head>
+ <body>
+ <div id="page-wrapper">
+ <div id="header" role="banner">
+ <header class="banner">
+ <div id="banner-text">
+ <span class="banner-title"><a href="/">beauhilton</a></span>
+ </div>
+ </header>
+ <nav>
+ <a href="/about">about</a>
+<a href="/now">now</a>
+<a class="nav-active" href="/posts">posts</a>
+<a href="https://notes.beauhilton.com">notes</a>
+<a href="https://talks.beauhilton.com">talks</a>
+<a href="https://git.beauhilton.com">git</a>
+<a href="/contact">contact</a>
+<a href="/feed.xml">rss</a>
+ </nav>
+ </div>
+ <main>
+ <h1>
+ Upgrading out-of-date OpenBSD installs
+ </h1>
+ <p>
+ <time id="post-date">2022-11-11</time>
+ </p>
+ <p id="post-excerpt">
+ First of all, don't do how I do.
+Upgrade your installs regularly.
+OpenBSD makes it very easy.
+ </p>
+ <p>
+ But, if you do happen to get behind…
+ </p>
+ <p>
+ <code>sysupgrade</code> is very likely to fail.
+ </p>
+ <h2>
+ What happens when you try to upgrade a very old install?
+ </h2>
+ <p>
+ Lots of 404 errors.
+ </p>
+ <p>
+ The <code>sysupgrade</code> utility tries to grab the next version of
+the OS from one of the many mirrors (the specific one your system will
+use is in <code>/etc/installurl</code>.)
+ </p>
+ <p>
+ The default mirrors only keep the last 2 or 3 versions around, so
+when <code>sysupgrade</code> constructs the url and tries to hit it for
+downloads, it will fail.
+ </p>
+ <h2>
+ Where to get old versions?
+ </h2>
+ <p>
+ There are a couple of mirrors that keep almost all the old versions
+around.
+ </p>
+ <p>
+ <a href="https://mirror.yandex.ru/pub/OpenBSD/">https://mirror.yandex.ru/pub/OpenBSD/</a>
+has files going back to OpenBSD 2.x - they seem like the most serious
+archivists, at least of the mirrors I looked at.
+ </p>
+ <p>
+ <a href="https://mirror.sjtu.edu.cn/OpenBSD/">https://mirror.sjtu.edu.cn/OpenBSD/</a>
+has files going back to 6.5 as of this writing (2022-11-11), also not
+too shabby.
+ </p>
+ <p>
+ Do a little <code>vi /etc/installurl</code> and change the link to
+one of the above, depending on how delinquent you’ve been.
+ </p>
+ <p>
+ That should allow you to do serial <code>sysupgrade</code> commands
+until you catch up.
+ </p>
+ <p>
+ When you get close to the current version, consider switching back to
+a closer mirror, both for faster installs and to be kind to the folks
+who just saved your bacon.
+ </p>
+ </main>
+ <div id="footnotes"></div>
+ <footer></footer>
+ </div>
+ </body>
+</html>
diff --git a/test/style.css b/test/style.css
@@ -0,0 +1,296 @@
+/** Variables **/
+
+:root
+{
+ --Canvas-bg: #201b1b;
+ --Canvas-color: #fff;
+ --Pre-bg: #151515;
+ --Pre-color: #fff;
+ --Pre-border: #222;
+ --Main-color: #f2f2f2;
+ --Code-color: #2adba4;
+ --Accent1-color: #2adba4; /* green */
+ --Accent2-color: #368aeb; /* blue */
+ --Highlight-num: #43a60d;
+ --Highlight-esc: #dfad06;
+ --Highlight-str: #f77f1d;
+ --Highlight-pps: #458759;
+ --Highlight-slc: #a0a0a0;
+ --Highlight-com: #a0a0a0;
+ --Highlight-ppc: #94e39;
+ --Highlight-opt: #ffffff;
+ --Highlight-ipl: #4dc987;
+ --Highlight-lin: #555555;
+ --Highlight-kwa: #d9396a;
+ --Highlight-kwb: #8655e7;
+ --Highlight-kwc: #ffffff;
+ --Highlight-kwd: #00a48f;
+}
+
+img {
+ display: inline-block;
+ max-width: 100%;
+}
+
+pre, code, sample {
+ white-space: pre-wrap;
+ hyphens: none;
+}
+
+table {
+ max-width: 100%;
+}
+
+html {
+ font-size: 70.5%;
+}
+
+body {
+ line-height: 1.5;
+ font-size: 1.6rem;
+ max-width: 38em;
+ margin: auto;
+ padding: 13px;
+}
+
+/* Structural blocks */
+
+#page-wrapper
+{
+ max-width: 88rem;
+
+ padding: 1rem 2rem 2rem;
+
+ margin-left: auto;
+ margin-right: auto;
+}
+
+
+/* Visual styles */
+
+html
+{
+ background: var(--Canvas-bg);
+ color: var(--Canvas-color);
+}
+
+header
+{
+ text-align: center;
+}
+
+::selection
+{
+ background: var(--Selection-bg);
+ color: var(--Selection-color);
+}
+
+/* shared gradient border */
+nav, footer
+{
+ border-width: 0;
+ border-style: solid;
+ border-color: var(--Accent1-color);
+ border-image: linear-gradient(to right, var(--Accent1-color), var(--Accent2-color)) 2;
+}
+
+nav
+{
+ font-size: 1.8rem;
+ border-bottom-width: 2px;
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+ word-spacing: 5px;
+ text-align: center;
+}
+
+main
+{
+ color: var(--Main-color);
+ text-rendering: optimizeLegibility;
+}
+
+footer
+{
+ text-align: center;
+ padding-top: 1rem;
+ margin-top: 1rem;
+ border-top-width: 2px;
+}
+
+div#banner-text
+{
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+}
+
+.banner
+{
+ display: flex;
+ flex-direction: row;
+ gap: 1rem;
+ justify-content: center;
+ align-items: center;
+ line-height: 1;
+}
+
+.banner-title
+{
+ margin: 0;
+ font-size: 3.6rem;
+ font-weight: 200;
+ letter-spacing: 0.425em;
+ /* letter-spacing is applied even to the last letter,
+ so for proper centering, we have to remove it ourselves, sadly */
+ margin-right: -0.425em;
+}
+
+.banner-title a
+{
+ text-decoration:none;
+ color: var(--Main-color);
+}
+
+.banner-title a:hover
+{
+ text-decoration:none;
+ color: var(--Accent1-color);
+}
+
+a {
+ color: var(--Accent2-color);
+}
+
+a:hover, a:focus
+{
+ text-decoration: underline;
+ color: var(--Accent1-color);
+}
+
+a.nav-active {
+ color: var(--Accent1-color);
+ font-weight: 200;
+}
+
+nav a { text-decoration: none; }
+
+a.here { text-decoration: none; }
+
+hr
+{
+ border: 0 none;
+ color: var(--Accent2-color);
+ background-color: currentColor;
+ height: 2px;
+}
+
+hr.footnotes { width: 40%; }
+
+a.footnote
+{
+ text-decoration: none;
+ margin-right: 0.4rem;
+}
+
+ul.toc { list-style: none; }
+
+h5 { font-size: 1.6rem; }
+h6 { font-size: 1.4rem; }
+
+code, kbd, samp
+{
+ color: var(--Code-color);
+}
+
+
+/** Typography */
+
+@supports (hyphens: auto)
+{
+ main
+ {
+ text-align: justify;
+ hyphens: auto;
+ }
+}
+
+body
+{
+ font-family: system-ui, sans-serif;
+ font-weight: 200;
+}
+
+table, th, td
+{
+ border: 1px solid var(--Accent1-color);
+ border-collapse: collapse;
+}
+
+th, td
+{
+ padding: 0.5em;
+ hyphens: none;
+ text-align: left;
+}
+
+.centered { text-align: center; }
+
+/* Style definition file generated by highlight 3.52, http://www.andre-simon.de/ */
+/* highlight theme: Kwrite Editor */
+body.hl { background-color: #e0eaee; }
+pre.hl { color: #000000; background-color:#e0eaee; font-size: 10pt; font-family: monospace; }
+.hl.num { color: var(--Highlight-num); }
+.hl.esc { color: var(--Highlight-esc); }
+.hl.str { color: var(--Highlight-str); }
+.hl.pps { color: var(--Highlight-pps); }
+.hl.slc { color: var(--Highlight-slc); font-style: italic; }
+.hl.com { color: var(--Highlight-com); font-style: italic; }
+.hl.ppc { color: var(--Highlight-ppc); }
+.hl.opt { color: var(--Highlight-opt); }
+.hl.ipl { color: var(--Highlight-ipl); }
+.hl.lin { color: var(--Highlight-lin); }
+.hl.kwa { color: var(--Highlight-kwa); font-weight: bold; }
+.hl.kwb { color: var(--Highlight-kwb); }
+.hl.kwc { color: var(--Highlight-kwc); font-weight: bold; }
+.hl.kwd { color: var(--Highlight-kwd); }
+
+pre
+{
+ box-sizing: border-box;
+ overflow: auto;
+ padding: 2rem;
+ margin-left: -2rem;
+ margin-right: -2rem;
+ border: 1px solid var(--Pre-border);
+ background: var(--Pre-bg);
+ color: var(--Pre-color);
+}
+
+pre code
+{
+ color: inherit;
+}
+
+@media screen and (max-width: 34em)
+{
+ .banner, .banner-title
+ {
+ display: block;
+ text-align: center;
+ margin: auto;
+ }
+ .banner
+ {
+ margin-bottom: 2rem;
+ }
+}
+
+@media screen and (max-width: 28em)
+{
+ .banner-title
+ {
+ font-size: 3.2rem;
+ }
+}
diff --git a/test/wants/index.html b/test/wants/index.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <link rel="stylesheet" href="/style.css" type="text/css">
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link rel="stylesheet" type="text/css" href="/style.css">
+ <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cstyle%3E %23m %7B opacity:0; %7D%0A@media (prefers-color-scheme: dark) %7B %23m %7B opacity:1; %7D %23e %7B opacity:0 %7D%0A%7D %3C/style%3E%3Ctext id='m' y='.9em' font-size='90'%3E🏕️%3C/text%3E%3Ctext id='e' y='.9em' font-size='90'%3E🌞%3C/text%3E%3C/svg%3E">
+ <title></title>
+ </head>
+ <body>
+ <div id="page-wrapper">
+ <div id="header" role="banner">
+ <header class="banner">
+ <div id="banner-text">
+ <span class="banner-title"><a href="/">beauhilton</a></span>
+ </div>
+ </header>
+ <nav>
+ <a href="/about">about</a>
+<a href="/now">now</a>
+<a href="/posts">posts</a>
+<a href="https://notes.beauhilton.com">notes</a>
+<a href="https://talks.beauhilton.com">talks</a>
+<a href="https://git.beauhilton.com">git</a>
+<a href="/contact">contact</a>
+<a href="/feed.xml">rss</a>
+ </nav>
+ </div>
+ <main>
+ <h1>
+ Wishlist
+ </h1>
+ <p>
+ While there are always <a href="https://rosewhitemusic.com/piano/writings/ten-thousand-things/#:~:text=%E2%80%9CThe%20Ten%20Thousand%20Things%E2%80%9D%20is,The%20One%20produced%20the%20two.">ten
+thousand material things</a> I want, some of which are in the Amazon
+Wishlist below, I’m more into digital capability these days.
+ </p>
+ <p>
+ Probably digital, use-anywhere gift cards are the way to go. E.g.
+Visa or MasterCard.
+ </p>
+ <h2>
+ beau@beauhilton.com
+ </h2>
+ <p>
+ I recently found <a href="https://www.fastmail.com/">fastmail</a>,
+which is a delightful mail service. I’m trying to be less reliant on
+Google, and using an independent email client is a big part of that.
+They charge money because they’re <em>not</em> doing all the stuff
+Google does to keep their products free, namely, using your info for ad
+targeting.
+ </p>
+ <p>
+ It’s $5 a month. I got a few months for free, and really like it. In
+addition to not selling your data, they have a good facility for having
+your own email extension (provided you own your domain), so I got
+<code>beau@beauhilton.com</code>. Any money toward supporting their
+service and keeping my cool new email address going would be much
+appreciated.
+ </p>
+ <h2>
+ beauhilton.com
+ </h2>
+ <p>
+ I use <a href="https://www.vultr.com/">Vultr</a> to host my server,
+which in turn hosts this website. It’s also $5 a month, which is a great
+deal for a server that I fully manage and is plenty powerful for a
+simple website.
+ </p>
+ <p>
+ Happy to receive any funds to support this going forward.
+ </p>
+ <h2>
+ Amazon
+ </h2>
+ <p>
+ And finally:
+ </p>
+ <p>
+ <a href="https://www.amazon.com/hz/wishlist/ls/3AKNW7PDL7STX?ref_=wl_share">Amazon
+Wishlist</a>
+ </p>
+ </main>
+ <div id="footnotes"></div>
+ <footer></footer>
+ </div>
+ </body>
+</html>