<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/pretty-atom-feed.xml" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>nycki.net</title>
  <subtitle>nycki.net</subtitle>
  <link href="https://nycki.net/blog/feed.xml" rel="self" />
  <link href="https://nycki.net/" />
  <updated>2025-11-03T00:00:00Z</updated>
  <id>https://nycki.net/</id>
  <author>
    <name>nycki</name>
  </author>
  <entry>
    <title>winpodman</title>
    <link href="https://nycki.net/blog/28/" />
    <updated>2025-11-03T00:00:00Z</updated>
    <id>https://nycki.net/blog/28/</id>
    <content type="html">&lt;p&gt;my windows machine is a surface tab 5 LTE from like 2015 and it has fairly limited internal storage so most of my code is on a 512GB microsd card that I leave connected at all times.&lt;/p&gt;
&lt;p&gt;this used to work fine. when you start WSL (windows subsystem for linux), it mounts C:&#92; as /mnt/c and D:&#92; as /mnt/d. But that doesn&#39;t seem to work anymore as of WSL 2.6.0, and rolling back didn&#39;t fix it either.&lt;/p&gt;
&lt;p&gt;apparently they &lt;a href=&quot;https://github.com/microsoft/WSL/issues/11931&quot;&gt;broke this on purpose?!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;on Podman Desktop you can work around this, using &lt;code&gt;podman machine ssh&lt;/code&gt; to go inside the Podman virtual machine and tinker with its drive mounts. So I did!&lt;/p&gt;
&lt;p&gt;Assuming you have Podman Desktop installed on Windows 10, do the following:&lt;/p&gt;
&lt;pre class=&quot;language-ps&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-ps&quot;&gt;podman machine stop
podman machine set --rootful
podman machine start
podman machine ssh
sudo echo &#39;D: /mnt/d drvfs defaults,uid=100,gid=1000 0 0&#39; &gt;&gt; /etc/fstab
sudo mkdir /mnt/d
sudo mount -a
exit&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;the &amp;quot;set --rootful&amp;quot; step is only needed if you want to give podman read-write access to files (e.g. if you are running a container that stores data on the host).&lt;/p&gt;
&lt;p&gt;now you should be able to run your &lt;a href=&quot;https://codeberg.org/nupanick/xp-php&quot;&gt;LAMP stack in podman&lt;/a&gt; on windows again :3&lt;/p&gt;
&lt;p&gt;ok bye!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Apache Slash-y</title>
    <link href="https://nycki.net/blog/27/" />
    <updated>2025-10-30T00:00:00Z</updated>
    <id>https://nycki.net/blog/27/</id>
    <content type="html">&lt;p&gt;gahhhhhh this was driving me crazy, putting it here so i don&#39;t lose it&lt;/p&gt;
&lt;p&gt;basically this solves the problem where you have pages like&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://example.com/page2/index.php?query=true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and you want it to display in the browser as the much nicer&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://example.com/page2?query=true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and you can&#39;t use nginx try_files because you promised yourself you were gonna make this work in apache &amp;quot;for old times&#39; sake&amp;quot;&lt;/p&gt;
&lt;p&gt;basically: this takes a surprisingly large number of rewrite rules. in order:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;remove trailing slashes, &lt;code&gt;page2/&lt;/code&gt; -&amp;gt; &lt;code&gt;page2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;remove file extensions, &lt;code&gt;page2.php&lt;/code&gt; -&amp;gt; &lt;code&gt;page2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;remove index filenames, &lt;code&gt;page2/index.php&lt;/code&gt; -&amp;gt; &lt;code&gt;page2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;oh yeah for EACH of those last three things, I hope you remembered to preserve the query string, so &lt;code&gt;page2/?query=true&lt;/code&gt; -&amp;gt; &lt;code&gt;page2?query=true&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;okay now you have a nice short URL in the browser. now just undo all that logic to get the actual php file to run on the server.&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;page2&lt;/code&gt; is a directory then serve from &lt;code&gt;page2/index.php&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;page2.php&lt;/code&gt; exists then serve from &lt;code&gt;page2.php&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;if none of those things exist then fall back on static file hosting. like, &lt;code&gt;page2.html&lt;/code&gt; might exist, you can serve that, sure, why not.&lt;/li&gt;
&lt;li&gt;oh you wanted to remove the html extension too? okay do all that again bozo.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;RewriteEngine On
&lt;span class=&quot;token comment&quot;&gt;#LogLevel alert rewrite:trace6&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# remove trailing slash&lt;/span&gt;
RewriteRule &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;/.*&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;/+&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;?.*&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;?$ &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;R&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# remove file extensions&lt;/span&gt;
RewriteCond %&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;DOCUMENT_ROOT&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;%&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;REQUEST_URI&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-f&lt;/span&gt;
RewriteRule &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;.*&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;.&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;php&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;html&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;?.*&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;?$ &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$3&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;NC,R&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# remove index.php index.html etc&lt;/span&gt;
RewriteCond %&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;DOCUMENT_ROOT&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;%&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;REQUEST_URI&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;-d
RewriteRule &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;.*&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;/index&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;?.*&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;?$ &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;NC,R&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# serve php file&lt;/span&gt;
RewriteCond %&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;DOCUMENT_ROOT&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;%&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;REQUEST_URI&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;.php &lt;span class=&quot;token parameter variable&quot;&gt;-f&lt;/span&gt;
RewriteRule &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;?.*&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;?$ fcgi://php:9000/usr/local/apache2/htdocs/%&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;REQUEST_URI&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;.php&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;P,L&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# serve php file with index&lt;/span&gt;
RewriteCond %&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;DOCUMENT_ROOT&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;%&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;REQUEST_URI&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;/ &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt;
RewriteCond %&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;DOCUMENT_ROOT&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;%&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;REQUEST_URI&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;/index.php &lt;span class=&quot;token parameter variable&quot;&gt;-f&lt;/span&gt;
RewriteRule &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;?.*&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;?$ fcgi://php:9000/usr/local/apache2/htdocs/%&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;REQUEST_URI&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;/index.php&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;P,L&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# serve html file&lt;/span&gt;
RewriteCond %&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;DOCUMENT_ROOT&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;%&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;REQUEST_URI&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;.html &lt;span class=&quot;token parameter variable&quot;&gt;-f&lt;/span&gt;
RewriteRule &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;^?&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;*&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;?.*&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;?$ &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;.html&lt;span class=&quot;token variable&quot;&gt;$2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# serve html file with index&lt;/span&gt;
RewriteCond %&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;DOCUMENT_ROOT&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;%&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;REQUEST_URI&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;/ &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt;
RewriteCond %&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;DOCUMENT_ROOT&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;%&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;REQUEST_URI&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;/index.html &lt;span class=&quot;token parameter variable&quot;&gt;-f&lt;/span&gt;
RewriteRule &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;^?&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;*&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;?.*&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;?$ &lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;/index.html&lt;span class=&quot;token variable&quot;&gt;$2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;L&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;some useful tricks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[NC] can be added after any regex rule to make it Non-Case sensitive.&lt;/li&gt;
&lt;li&gt;[R] means &amp;quot;in-browser redirect&amp;quot; and is used when you want to fix a URI on the user&#39;s side. if you don&#39;t do this then it only affects where the server pulls data from.&lt;/li&gt;
&lt;li&gt;[P] means &amp;quot;proxy&amp;quot; and it allows you to have the server pull data from another machine or from a program running on a local port.&lt;/li&gt;
&lt;li&gt;[L] means &amp;quot;last one&amp;quot; and it skips all remaining rewrite rules, in case you were worried about matching too many of them.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;all this and more can be found at &lt;a href=&quot;https://httpd.apache.org/docs/current/mod/mod_rewrite.html&quot;&gt;the apache2 docs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;if there&#39;s an easy way to do all this then please please tell me, I miss try_files so much, holy cow.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>on the nature of magic</title>
    <link href="https://nycki.net/blog/26/" />
    <updated>2025-07-01T00:00:00Z</updated>
    <id>https://nycki.net/blog/26/</id>
    <content type="html">&lt;p&gt;I used to think magic was about knowing secret stuff. Then I thought magic was about being really good at acting and sleight of hand. Now I think those are both just facets of what really makes a moment feel magical: being more prepared than anyone could reasonably anticipate.&lt;/p&gt;
&lt;p&gt;By this &amp;quot;overprepared&amp;quot; metric, &amp;quot;magic&amp;quot; includes stage illusions and street magic, but it also includes things like when you think you&#39;ve broken the rules of a video game and gotten yourself out of bounds, only to find a sign congratulating you on your cleverness. Or when you throw something at a game master that should send the game off the rails, and yet they have the next map already drawn up for you.&lt;/p&gt;
&lt;p&gt;Every &amp;quot;The Dev Team Thought Of Everything&amp;quot; moment is a magic trick, and vice versa.&lt;/p&gt;
&lt;p&gt;And I think, in that context, it&#39;s possible to enjoy magic even after you know the secret. The best magicians are the ones that make you say &amp;quot;I think I know &lt;em&gt;how&lt;/em&gt; that works...&lt;/p&gt;
&lt;p&gt;...but it &lt;em&gt;shouldn&#39;t&lt;/em&gt;.&amp;quot;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>partycraft</title>
    <link href="https://nycki.net/blog/25/" />
    <updated>2025-06-25T00:00:00Z</updated>
    <id>https://nycki.net/blog/25/</id>
    <content type="html">&lt;p&gt;&lt;em&gt;We have liftoff&lt;/em&gt;: local multiplayer Minecraft on the same Steam Deck.&lt;/p&gt;
&lt;img src=&quot;https://nycki.net/a/photo-splitcraft.jpg&quot; alt=&quot;Minecraft running in splitscreen on a Steam Deck, with two pairs of Nintendo Joy-Cons as the controllers.&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;in Desktop mode, download &lt;a href=&quot;https://github.com/wunnr/partydeck-rs&quot;&gt;PartyDeck&lt;/a&gt; 0.3.2, the PartyDeck config for Minecraft, the &amp;quot;Vertical split for 2 players&amp;quot; config, and the Prism Portable launcher (the flatpak will not work for this). If you want separate skins for p1 and p2, download those now.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Extract PartyDeck and Prism to their own folders, like ~/Games/partydeck and ~/Games/prism.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;run PrismLauncher for the first time and log into your Minecraft account. Add two &amp;quot;offline&amp;quot; accounts, I named mine &amp;quot;red&amp;quot; and &amp;quot;blue&amp;quot;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a new instance of 1.20.1 Fabric named Splitscreen Red with these mods:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;fabric api 0.86.1&lt;/li&gt;
&lt;li&gt;fabric tailor 2.1.2&lt;/li&gt;
&lt;li&gt;midnight controls 1.9.4&lt;/li&gt;
&lt;li&gt;splitscreen 0.0.2&lt;/li&gt;
&lt;li&gt;whoami 1.0&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Place your skins in the instance folder, for example mine are in minecraft/skins.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Under Settings -&amp;gt; Miscellaneous, set Account to &amp;quot;red&amp;quot;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a duplicate of that instance named Splitscreen Blue, and set its Account to &amp;quot;blue&amp;quot;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Following the PartyDeck readme, set up a steam shortcut to PartyDeckKWinLaunch.sh.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Launch PartyDeck, select Minecraft -&amp;gt; Play. You will be prompted to select the folder where you installed Prism Launcher earlier.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Under PartyDeck settings, enable &amp;quot;Vertical split for 2 players&amp;quot;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Reboot into Gaming Mode.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Make sure you have connected two controllers and a mouse.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Launch PartyDeck from Gaming Mode.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Select Minecraft -&amp;gt; Play. Press &amp;quot;a&amp;quot; (or whatever the south button is) on both controllers, then press &amp;quot;start&amp;quot; on player 1&#39;s controller.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;This will start two copies of Prism. Using the mouse, launch the Red instance for player 1 and the Blue instance for player 2. Fullscreening both instances should Just Work, but if it doesn&#39;t, connect a keyboard and press F11 repeatedly to cycle through the different configs for the Splitscreen mod.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Have player 1 start a singleplayer world, and open it to LAN.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Have player 2 join via the multiplayer menu.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Each player should now set their skin using this command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/skin set upload &amp;lt;original|slim&amp;gt; skins/&amp;lt;skin.png&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If the skins do not render correctly, have both players exit and re-launch the game.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At this point you should be good to go! You have two copies of minecraft running in splitscreen on one computer, with different names and avatars for each player, in the same world.&lt;/p&gt;
&lt;p&gt;This took me like three days to figure out. If it helped you, please send me an email!&lt;/p&gt;
&lt;p&gt;map shown here is &lt;a href=&quot;https://www.planetminecraft.com/project/questioning-6255171/&quot;&gt;Questioning&lt;/a&gt; by Infernally. skins are &lt;a href=&quot;https://www.planetminecraft.com/member/ayahanna/submissions/?keywords=panty&quot;&gt;Panty and Stocking&lt;/a&gt; by Ayahanna.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>balatro homebrew</title>
    <link href="https://nycki.net/blog/24/" />
    <updated>2025-04-25T00:00:00Z</updated>
    <id>https://nycki.net/blog/24/</id>
    <content type="html">&lt;p&gt;&lt;em&gt;cross-posted from &lt;a href=&quot;https://bark.lgbt/@nycki/114395352312097076&quot;&gt;https://bark.lgbt/@nycki/114395352312097076&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;*update 2025-05-03: you might have better luck using the &lt;a href=&quot;https://portmaster.games/&quot;&gt;PortMaster Script&lt;/a&gt; for this game! They seem pretty cool, long list of games they&#39;ve patched to run on low-end hardware. I haven&#39;t installed mods on this version yet but I&#39;ll try it later.&lt;/p&gt;
&lt;p&gt;I got modded balatro to &lt;em&gt;mostly&lt;/em&gt; run under Switchroot Ubuntu. There&#39;s a bunch of mods that are complaining about bad filesystem access and I haven&#39;t dug in to isolate the problem yet. For my own notes tho, here&#39;s what I know:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;install Switchroot Ubuntu Noble, see here &lt;a href=&quot;https://wiki.switchroot.org/wiki/linux/l4t-ubuntu-noble-installation-guide&quot;&gt;https://wiki.switchroot.org/wiki/linux/l4t-ubuntu-noble-installation-guide&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;do &lt;em&gt;not&lt;/em&gt; install the system default love package, it has a bad filesystem hook. &lt;a href=&quot;https://www.love2d.org/forums/viewtopic.php?t=93348e&quot;&gt;https://www.love2d.org/forums/viewtopic.php?t=93348e&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;install love=11.5ppa from bartbes&#39;s repo. &lt;a href=&quot;https://launchpad.net/~bartbes/+archive/ubuntu/love-stable&quot;&gt;https://launchpad.net/~bartbes/+archive/ubuntu/love-stable&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;copy Balatro.exe from another computer. you don&#39;t need any of the dlls it comes with.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;install rust: &lt;a href=&quot;https://www.rust-lang.org/tools/install&quot;&gt;https://www.rust-lang.org/tools/install&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;use rust to compile lovely-injector, following WilsontheWolf&#39;s steps &lt;a href=&quot;https://github.com/ethangreen-dev/lovely-injector/issues/189#issuecomment-2814397769&quot;&gt;https://github.com/ethangreen-dev/lovely-injector/issues/189#issuecomment-2814397769&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;run this command to start the game:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;LD_PRELOAD&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;liblovely.so love Balatro.exe&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;place mods in ~/.config/love/Mods/.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;TODO:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;load mods from another folder, such as .config/balatro/.&lt;/li&gt;
&lt;li&gt;figure out why some mods crash when loading textures.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>filebrowser auth</title>
    <link href="https://nycki.net/blog/23/" />
    <updated>2025-03-16T00:00:00Z</updated>
    <id>https://nycki.net/blog/23/</id>
    <content type="html">&lt;p&gt;I FINALLY GOT IT WORKING&lt;/p&gt;
&lt;p&gt;docker-compose.yml&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;filebrowser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;filebrowser/filebrowser:s6&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;container_name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;filebrowser&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;# filebrowser will run as this user, you may want to create a new one&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PUID=1000&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;PGID=1000&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;unless-stopped&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/data/filebrowser/srv:/srv&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/data/filebrowser/database:/database&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/data/filebrowser/config:/config&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;8200:80&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;docker-compose&lt;/span&gt; up &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;log into filebrowser as admin and do your setup, then:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;docker-compose&lt;/span&gt; down
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;docker-compose&lt;/span&gt; run &lt;span class=&quot;token parameter variable&quot;&gt;--entrypoint&lt;/span&gt; /bin/bash filebrowser
filebrowser config &lt;span class=&quot;token builtin class-name&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--auth.method&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;proxy &lt;span class=&quot;token parameter variable&quot;&gt;--auth.header&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;X-Remote-User
&lt;span class=&quot;token builtin class-name&quot;&gt;exit&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;docker-compose&lt;/span&gt; up &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;filebrowser is now expecting to get a header with the authenticated username. We can give it that! install the pwauth authenticator:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; libapache2-mod-authnz-external pwauth
a2enmod authnz_external&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and configure it like this:&lt;/p&gt;
&lt;pre class=&quot;language-xml&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;VirtualHost&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;*:&lt;/span&gt;443&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  ServerName fb.hatspace.net
  DefineExternalAuth pwauth pipe /usr/sbin/pwauth
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Proxy&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    Order deny,allow
    Allow from all
    AuthType Basic
    AuthName &quot;Login&quot;
    AuthBasicProvider external
    AuthExternal pwauth
    Require valid-user
    RequestHeader set X-Remote-User %{REMOTE_USER}s
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Proxy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Location&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    # filebrowser
    ProxyPass http://localhost:8200/ nocanon
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Location&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That &lt;code&gt;%{REMOTE_USER}s&lt;/code&gt; is not a typo, the s is important! I think it stands for &amp;quot;ssl&amp;quot; or &amp;quot;secure&amp;quot; or something? You need it or the var will be null.&lt;/p&gt;
&lt;p&gt;and viola! the server will now allow you to log in with your linux username and password, and filebrowser will show the correct files when you do!&lt;/p&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://filebrowser.org/installation&quot;&gt;https://filebrowser.org/installation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/724599/setting-up-an-apache-proxy-with-authentication&quot;&gt;https://stackoverflow.com/questions/724599/setting-up-an-apache-proxy-with-authentication&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://serverfault.com/questions/45278/authenticate-in-apache-via-system-account&quot;&gt;https://serverfault.com/questions/45278/authenticate-in-apache-via-system-account&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://serverfault.com/questions/207301/get-the-authenticated-user-under-apache&quot;&gt;https://serverfault.com/questions/207301/get-the-authenticated-user-under-apache&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Update 2025-03-17: Don&#39;t do this until this issue is resolved: &lt;a href=&quot;https://github.com/filebrowser/filebrowser/issues/2658&quot;&gt;https://github.com/filebrowser/filebrowser/issues/2658&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Basically: filebrowser does all operations as root, including file creation. So even if you restrict a user to their home directory, all the files they create will belong to root. Less than ideal. I&#39;m looking into &lt;a href=&quot;https://github.com/misterunknown/ifm&quot;&gt;ifm&lt;/a&gt; as an alternative.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>flavored types</title>
    <link href="https://nycki.net/blog/22/" />
    <updated>2025-02-04T00:00:00Z</updated>
    <id>https://nycki.net/blog/22/</id>
    <content type="html">&lt;p&gt;hey so I like programming! I do it for money sometimes. I&#39;m gonna talk about an interesting problem and its solution that I observed today. if you don&#39;t enjoy code for the sake of code, you can skip this one! or, if you already know what TypeScript is, you can skip ahead to &lt;a href=&quot;https://nycki.net/blog/22/#the-problem&quot;&gt;the problem&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;context&quot; tabindex=&quot;-1&quot;&gt;context &lt;a class=&quot;header-anchor&quot; href=&quot;https://nycki.net/blog/22/#context&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;so there&#39;s this software I use all the time called TypeScript, which is like JavaScript but with types. would you like a contrived example to show why I use it? I bet you would!&lt;/p&gt;
&lt;p&gt;here&#39;s a snippet of JavaScript code I might write to generate some repetitive text, like the 99 bottles of beer song.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;99&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;bottles of beer on the wall&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;counting down like this will work just fine. But if I do the opposite:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;on the &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;th day of christmas...&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;this won&#39;t work correctly! It&#39;ll do something like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;on the 1th day of christmas...
on the 11th day of christmas...
on the 111th day of christmas...&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;that&#39;s because I&#39;ve mistakenly defined &lt;code&gt;n&lt;/code&gt; as &lt;code&gt;&#39;1&#39;&lt;/code&gt;, in quotes, which means it&#39;s actually a string, and not a number. when you do math on things that aren&#39;t numbers, &lt;em&gt;sometimes&lt;/em&gt; it works how you expect, but not &lt;em&gt;always&lt;/em&gt;. it would be nice if I had a way to scan my source code and say &amp;quot;whoops, did I ever treat the same thing as a string and a number without meaning to do that?&amp;quot; enter TypeScript:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; 
  &lt;span class=&quot;token comment&quot;&gt;// TYPE ERROR: Operator &#39;&amp;lt;=&#39; cannot be applied to types &#39;string&#39; and &#39;number&#39;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;TypeScript sees that I messed up, and it says &amp;quot;hey, that&#39;s not something you would normally do with the less-than-or-equal operator. check your types.&amp;quot;&lt;/p&gt;
&lt;p&gt;you can also tell typescript intentionally &#39;hey, I am expecting this to be a type&#39; and it&#39;ll throw the error even earlier:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; n&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Type &#39;string&#39; is not assignable to type &#39;number&#39;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;the-problem&quot; tabindex=&quot;-1&quot;&gt;the problem &lt;a class=&quot;header-anchor&quot; href=&quot;https://nycki.net/blog/22/#the-problem&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;okay so typescript is too clever for its own good. if two types look the same, they are the same. so I can tell typescript &amp;quot;hey, assign this string to that string&amp;quot; and it&#39;ll say &amp;quot;sure&amp;quot; even if those strings have differently named types.&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Color&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; name1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Alice&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; color1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Color &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// no error?&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;most of the time this is fine. if it fits, it fits. but what if I want this to throw an error? one solution is &amp;quot;flavoring&amp;quot;, as given in &lt;a href=&quot;https://spin.atomicobject.com/typescript-flexible-nominal-typing/&quot;&gt;this excellent 2018 article by Drew Colthorp&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;basically, I add a &amp;quot;fake property&amp;quot; to the &lt;code&gt;Name&lt;/code&gt; and &lt;code&gt;Color&lt;/code&gt; types, and then TypeScript will know they&#39;re not interchangeable.&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; type&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Name&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Color&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; type&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Color&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; name1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Alice&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Type &#39;string&#39; is not assignable to type &#39;Name&#39;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;...uh. TypeScript doesn&#39;t like that anymore; it knows that &lt;code&gt;&#39;Alice&#39;&lt;/code&gt; can&#39;t possibly be a &lt;code&gt;Name&lt;/code&gt; because it doesn&#39;t have that extra field. And we can&#39;t &lt;em&gt;actually&lt;/em&gt; add that data because strings are a primitive type, they don&#39;t &lt;em&gt;have&lt;/em&gt; fields, this whole thing is just a fiction to make TypeScript understand that names and colors are different kinds of strings.&lt;/p&gt;
&lt;p&gt;that&#39;s fine though! we&#39;ll make the field &lt;em&gt;optional&lt;/em&gt; so that TypeScript doesn&#39;t care whether we use it or not. and while we&#39;re at it, we&#39;ll make it &lt;em&gt;readonly&lt;/em&gt; so TypeScript doesn&#39;t think we can write to it.&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;readonly&lt;/span&gt; type&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Name&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Color&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;readonly&lt;/span&gt; type&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Color&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; name1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Alice&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; color1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Color &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Type &#39;Name&#39; is not assignable to type &#39;Color&#39;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;bingo! just what we wanted. now if we accidentally mix-up these types later, we&#39;ll get a nice friendly error message about it.&lt;/p&gt;
&lt;p&gt;if we want to use these types a lot, we might make a &lt;em&gt;type pattern&lt;/em&gt; to describe it:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FlavoredString&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;readonly&lt;/span&gt; type&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FlavoredString&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Name&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Color&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FlavoredString&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Color&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;we could even make the pattern &lt;em&gt;fully&lt;/em&gt; generic, but then we have to handle the case that &lt;code&gt;type&lt;/code&gt; already exists on the thing we&#39;re adding flavor to. thankfully, the standard library provides the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol&quot;&gt;Symbol&lt;/a&gt; type. a Symbol is just like a string except that it&#39;s guaranteed to be unique, meaning it won&#39;t be any of the existing properties on our base object. we don&#39;t even have to make a real symbol, we can just tell typescript &amp;quot;imagine a symbol&amp;quot;.&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; flavor&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; unique &lt;span class=&quot;token builtin&quot;&gt;symbol&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Flavored&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;readonly&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;flavor&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;F&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Flavored&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Name&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Color&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Flavored&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Color&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; name1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Alice&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; color1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Color &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// Type &#39;Name&#39; is not assignable to type &#39;Color&#39;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;remember, the &lt;code&gt;[flavor]&lt;/code&gt; property doesn&#39;t really exist, it&#39;s a fiction we made up for TypeScript to catch our errors. in the output code, &lt;code&gt;name1&lt;/code&gt; will still just be a string.&lt;/p&gt;
&lt;p&gt;and there you go! now you can be extra pedantic about all those database ids being thrown around in your code. they&#39;re not &lt;em&gt;really&lt;/em&gt; all the same type, right? you wouldn&#39;t assign an id string to a display string, &lt;em&gt;&lt;strong&gt;right?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>rss.svg</title>
    <link href="https://nycki.net/blog/21/" />
    <updated>2024-12-28T00:00:00Z</updated>
    <id>https://nycki.net/blog/21/</id>
    <content type="html">&lt;p&gt;Today I added the &lt;a href=&quot;https://en.wikipedia.org/wiki/RSS&quot;&gt;RSS&lt;/a&gt; icon ( &lt;svg width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt; ) to my site! You should be able to see it up top by the word &amp;quot;blog&amp;quot; in the navbar, and if you click on it, it pulls up the RSS feed that you can subscribe to! As an aside, my current preferred reader is &lt;a href=&quot;https://www.freshRSS.org/&quot;&gt;FreshRSS&lt;/a&gt;, but the nice thing about RSS readers is that they all have a standard import/export format so you can switch whenever you want :)&lt;/p&gt;
&lt;p&gt;Anyway, I did this in a couple of steps. First I went searching for existing art that I can freely use, and I found &lt;a href=&quot;https://www.svgrepo.com/svg/95552/rss-sign&quot;&gt;this one on SVG Repo&lt;/a&gt; with a &lt;a href=&quot;https://creativecommons.org/public-domain/cc0/&quot;&gt;CC0 License&lt;/a&gt;. Thanks, SVG Repo!&lt;/p&gt;
&lt;p&gt;I modified the SVG to use &lt;code&gt;fill=&amp;quot;currentColor&amp;quot;&lt;/code&gt;, and I import it like this:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;svg&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;0.8em&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;0.8em&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;use&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;/a/rss.svg#img&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;svg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since the fill color is set based on the font color, it&#39;ll always match my theme! Here&#39;s a bunch of different colored RSS icons for fun.&lt;/p&gt;
&lt;p&gt;&lt;svg color=&quot;var(--xkcd-magenta)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-red)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-orange)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-yellow)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-green)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-teal)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-blue)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-purple)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/p&gt;
&lt;p&gt;&lt;svg color=&quot;var(--xkcd-pink)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-lightblue)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-white)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-lightblue)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-pink)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-white)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-pink)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-lightblue)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/p&gt;
&lt;p&gt;&lt;svg color=&quot;var(--xkcd-yellow)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-yellow)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-white)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-white)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-purple)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-purple)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-dark-grey)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;
&lt;svg color=&quot;var(--xkcd-dark-grey)&quot; width=&quot;0.8em&quot; height=&quot;0.8em&quot;&gt;&lt;use href=&quot;../../a/rss.svg#img&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>server move</title>
    <link href="https://nycki.net/blog/20/" />
    <updated>2024-12-27T00:00:00Z</updated>
    <id>https://nycki.net/blog/20/</id>
    <content type="html">&lt;p&gt;up until now ive been hosting my site on a DigitalOcean droplet with 8GB of memory. the reason being that that&#39;s how much I needed to play Minecraft: Vault Hunters. But that costs like $40 a month and I don&#39;t play minecraft all that much anymore. so I&#39;m downsizing.&lt;/p&gt;
&lt;p&gt;I&#39;ve temporarily downgraded that server to its minimum, and I&#39;m spinning up a new server which is even smaller than that. DigitalOcean has a $6/mo tier which gives you 10 GB storage and 1 GB memory, which is &lt;em&gt;plenty&lt;/em&gt; for hosting a personal site. Heck, its probably enough to host &lt;em&gt;several&lt;/em&gt; personal sites. And if storage is an issue... well, I&#39;ll figure that out later, but even paying by the gigabyte, storage is cheaper than memory.&lt;/p&gt;
&lt;p&gt;Oh yeah also: you might notice that the url for this entry is currently &lt;em&gt;/b/20&lt;/em&gt;. I&#39;m making all my urls shorter, just because I can. This is gonna break a few permalinks, but oh well. I trust y&#39;all will figure it out.&lt;/p&gt;
&lt;p&gt;Oh! Speaking of which: the source is visible at &lt;a href=&quot;https://git.hatspace.net/nycki/nycki.net&quot;&gt;https://git.hatspace.net/nycki/nycki.net&lt;/a&gt;. If you want a site hosted on hatspace, just drop me a line! Currently I&#39;m running static hosting with apache2 but at some point I&#39;ll figure out php and/or expressjs, I swear.&lt;/p&gt;
&lt;p&gt;Also check out the new &lt;a href=&quot;https://nycki.net/characters&quot;&gt;characters&lt;/a&gt; page! :3&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>automatic rebuilding</title>
    <link href="https://nycki.net/blog/2024-12-24-automatic-rebuilding/" />
    <updated>2024-12-24T11:38:00Z</updated>
    <id>https://nycki.net/blog/2024-12-24-automatic-rebuilding/</id>
    <content type="html">&lt;p&gt;this page was built with &lt;a href=&quot;https://forgejo.org/&quot;&gt;forgejo&lt;/a&gt;, yo!&lt;/p&gt;
&lt;p&gt;I installed a git forge on my own server so I can upload whatever I want, including nsfw stuff if I feel like it, and I wrote this build script that automatically rebuilds the page whenever I push changes.&lt;/p&gt;
&lt;p&gt;And I&#39;m currently editing this page in &lt;a href=&quot;https://decapcms.org/&quot;&gt;Decap CMS&lt;/a&gt;, which automatically pushes changes to a git forge.&lt;/p&gt;
&lt;p&gt;So I have a fully visual post editor now!&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 
  &lt;span class=&quot;token key atrule&quot;&gt;workflow_dispatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;branches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;main&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    
&lt;span class=&quot;token key atrule&quot;&gt;jobs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;runs-on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;hosted
    &lt;span class=&quot;token key atrule&quot;&gt;steps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; actions/checkout@v4
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; actions/setup&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;node@v4
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; npm ci
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; npm run build
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; mkdir &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;p /data/nycki.net/site
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cp site.conf /data/nycki.net/site.conf
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cp &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;r _site/* /home/nycki/nycki.net/patches/* /data/nycki.net/site/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://nycki.net/a/decap-cms.jpg&quot; alt=&quot;screenshot of the editor used to write this post&quot; title=&quot;screenshot of the editor used to write this post&quot;&gt;&lt;/p&gt;
&lt;p&gt;You would think I&#39;m thrilled with this, and I am, on some level, but I&#39;m also really annoyed. My stack now includes Debian, NodeJS, Eleventy, Git, Docker, Forgejo, Forgejo Actions (which have to be installed manually), and Decap CMS. That&#39;s... that&#39;s just so much junk, just to be able to post in a web browser and have it kinda work as a website updater. Heaven forbid I ever try to duplicate this setup for a friend or family member. Please email me or leave a comment if you know a better way to get the basic functionality of &amp;quot;post in a web browser and publish to a website.&amp;quot;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>decap cms</title>
    <link href="https://nycki.net/blog/2024-12-14-decap-cms/" />
    <updated>2024-12-14T14:47:00Z</updated>
    <id>https://nycki.net/blog/2024-12-14-decap-cms/</id>
    <content type="html">&lt;p&gt;if u can read this than i installed the decap editor for my site :3&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://nycki.net/a/1000244319.png&quot; alt=&quot;screenshot of decap, the editor i wrote this in&quot; title=&quot;screenshot of decap, the editor i wrote this in&quot;&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>chost</title>
    <link href="https://nycki.net/blog/2024-12-13-01-chost/" />
    <updated>2024-12-13T00:00:00Z</updated>
    <id>https://nycki.net/blog/2024-12-13-01-chost/</id>
    <content type="html">&lt;p&gt;idea: a shirt with text on the boobs that says &#39;eye contact is overrated&#39;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>can opener</title>
    <link href="https://nycki.net/blog/2024-12-05-01-can-opener/" />
    <updated>2024-12-05T00:00:00Z</updated>
    <id>https://nycki.net/blog/2024-12-05-01-can-opener/</id>
    <content type="html">&lt;p&gt;If I ask you what a can opener is, and you say&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A can opener is a service component that affords access to preserved fruits and vegetables.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This does not help me at all. I am looking for something along the lines of&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A can opener is a handheld metal tool that cuts the lids off of canned food, which you can buy at the grocery store. You use it by turning a knob, which puts pressure on two blades, which cut through the metal lid of the can.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Thank you.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>the software golem</title>
    <link href="https://nycki.net/blog/2024-11-25-01-software-golem/" />
    <updated>2024-11-25T00:00:00Z</updated>
    <id>https://nycki.net/blog/2024-11-25-01-software-golem/</id>
    <content type="html">&lt;p&gt;they said it was not worth our time to fix. the code could be obsolete any day now. better to keep it running until then. just keep fixing it until the requirements change, and then we can make a new one.&lt;/p&gt;
&lt;p&gt;but the requirements never change all at once. it happens little by little, like rotting planks stripped from a wooden boat, replaced with fresh boards until no trace of the original remains.&lt;/p&gt;
&lt;p&gt;and the repairs are never perfect. the new boat is not just made of new wood. it is also made of nails, and glue, and paint that doesn&#39;t quite match. the floor is not level, the walls are not watertight, the sails don&#39;t unfurl unless you climb up there and jiggle it the right way. i don&#39;t know anything about boats but you get the idea.&lt;/p&gt;
&lt;p&gt;and the code does not exist all in one place. you cannot simply download and run it, for it relies on services, which you cannot simply simulate because they rely on the cloud; the code is like those fish that only live in one pond in a crater in the middle of nowhere; the code is so perfectly adapted to these conditions that it could not survive anywhere else, not on your machine, not on mine.&lt;/p&gt;
&lt;p&gt;and the code does not exist entirely on computers either, because it has adapted to run in a world where admins and developers are using it, and the code relies on this input. sometimes one of us organic beings has to manually delete some bad data, or reboot a blocked process, and sometimes i watch loading bars for twenty minutes because i am waiting for the program and the program is waiting for me. it&#39;s a child, it cannot be left unattended.&lt;/p&gt;
&lt;p&gt;so now this thing exists. it is like a machine made of scrap wood, living in an acid puddle, operated by some senior engineer with a name like &#39;dave&#39;, and it absolutely must be kept alive.&lt;/p&gt;
&lt;p&gt;we can&#39;t afford to replace it. but we also can&#39;t afford &lt;em&gt;not&lt;/em&gt; to replace it. so just add that idea to the &#39;tech debt&#39; tracker, and in the meantime could you get it to accept data with misspelled words in it? we don&#39;t have a list of all the words to fix, just sorta look through the logs for anything that might be a mistake and patch it.&lt;/p&gt;
&lt;p&gt;that&#39;ll buy us a few more months.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Paper Pyramids</title>
    <link href="https://nycki.net/blog/2024-11-22-01-origami-pyramids/" />
    <updated>2024-11-22T00:00:00Z</updated>
    <id>https://nycki.net/blog/2024-11-22-01-origami-pyramids/</id>
    <content type="html">&lt;img src=&quot;https://nycki.net/blog/2024-11-22-01-origami-pyramids/paper-pyramid-nest.webp&quot; alt=&quot;three paper pyramids of different sizes, laying on the table as if a stack were just tipped over.&quot;&gt;
&lt;p&gt;So apparently I haven&#39;t written about &lt;a href=&quot;https://www.looneylabs.com/pyramids-home&quot;&gt;Looney Pyramids&lt;/a&gt; yet! Formerly known as Icehouse Pyramids, these were invented by Andy Looney in 1987 as a prop for a science fiction setting for his book &lt;a href=&quot;http://archive.wunderland.com/WTS/Andy/EmptyCity/emptycity.html&quot;&gt;The Empty City&lt;/a&gt;. The game was called Icehouse, and it was meant to be a Martian counterpart to Chess, but &amp;quot;alien&amp;quot; in every possible way:&lt;/p&gt;
&lt;img src=&quot;https://nycki.net/blog/2024-11-22-01-origami-pyramids/paper-pyramid-bottlecap.webp&quot; alt=&quot;a paper pyramid next to a bottlecap, for scale. the pyramid is about half an inch wide at the base.&quot;&gt;
&lt;ul&gt;
&lt;li&gt;The game is for 4 players, with no assigned partners. Diplomacy is allowed but &lt;a href=&quot;https://ee0r.com/icehouse/hypothermia/07/default.html&quot;&gt;only once play begins&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Pieces cannot be moved after placing, except in rare circumstances, similar to Go.&lt;/li&gt;
&lt;li&gt;There is no board! The game is played on any flat surface, typically a coffee table. Each player is allowed a small reserve space for their &#39;out of play&#39; pieces, and &lt;em&gt;literally everywhere else&lt;/em&gt; is considered &#39;in play&#39;.&lt;/li&gt;
&lt;li&gt;There are &lt;em&gt;no turns&lt;/em&gt;. You can move whenever you feel like it. You can make lots of quick moves, or you can wait and make lots of late moves.&lt;/li&gt;
&lt;li&gt;To prevent stalling, there is a timer set to &#39;about 30 minutes&#39;, and placed where nobody can see the remaining time.&lt;/li&gt;
&lt;/ul&gt;
&lt;img src=&quot;https://nycki.net/blog/2024-11-22-01-origami-pyramids/paper-pyramid-comparison.webp&quot; alt=&quot;the paper pyramid compared to a plastic Looney Pyramid. it&#39;s about the same size.&quot;&gt;
&lt;p&gt;These design concepts were ahead of their time in my opinion. Andy Looney and friends, I think they called themselves the &#39;Wunderland Toast Society&#39;, they absolutely changed board gaming in a way we wouldn&#39;t see again until James Ernest started Cheapass Games and started selling cut-and-play titles like &lt;a href=&quot;https://crabfragmentlabs.com/shop/p/kill-doctor-lucky&quot;&gt;Kill Doctor Lucky&lt;/a&gt; in 1996. In fact, whenever a James Ernest game says to use &#39;tokens of your choice&#39;, I always use Looney Pyramids.&lt;/p&gt;
&lt;img src=&quot;https://nycki.net/blog/2024-11-22-01-origami-pyramids/paper-pyramid-tree.webp&quot; alt=&quot;three paper pyramids stacked upright in a pine tree shape, with a hand visible holding them in place.&quot;&gt;
&lt;p&gt;Anyway, I had to blog about this because I found Bill Adams&#39; &lt;a href=&quot;https://web.archive.org/web/20050521082358/http://www.iglou.com/biladams/IceHouse/&quot;&gt;Origami Icehouse Pieces&lt;/a&gt; page buried in the Internet Archive. I&#39;ve downloaded a local copy in case anything happens to the Archive and I&#39;ll probably mirror it at some point &lt;a href=&quot;https://nycki.net/blog/2024-09-21-01-ethics-of-reuploading/&quot;&gt;unless he objects&lt;/a&gt;. I&#39;m not sure if he&#39;s still around or how to get in touch with him; if you do then let me know.&lt;/p&gt;
&lt;p&gt;The pieces are a bit tricky to fold! When he says &amp;quot;fold the corner to the right&amp;quot;, you actually have to hold the previous fold in place and fold over it. I should take my own pictures honestly. Right now I just want to show off a few pieces I folded for fun though. Ok bye!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Thumbkey</title>
    <link href="https://nycki.net/blog/2024-11-21-01-thumbkey/" />
    <updated>2024-11-21T00:00:00Z</updated>
    <id>https://nycki.net/blog/2024-11-21-01-thumbkey/</id>
    <content type="html">&lt;img src=&quot;https://nycki.net/blog/2024-11-21-01-thumbkey/thumbkey.png&quot; alt=&quot;a phone screenshot, showing a text editor and an on-screen keyboard. the keyboard has large, square keys, with a 3 by 3 grid in the center and 5 additional keys along the bottom and right edges. the entered text reads &#39;sphinx of black quartz, I have recently come into a large inheritance outside of my country and I require your assistance&#39;, referring to the Nigerian Prince email scam cliche.&quot; style=&quot;float:right;margin:2ch&quot;&gt;
&lt;p&gt;Today I&#39;d like to spotlight a keyboard I&#39;ve been using since the day I got my first keyless android phone circa 2012. It was a tiny little thing, screen the size of a business card, and they had the nerve to ship it without a numpad or keyboard attached!&lt;/p&gt;
&lt;p&gt;Some people worked around this problem by using speech to text, or by using an auto-complete tool like &lt;a href=&quot;https://en.wikipedia.org/wiki/Swype&quot;&gt;Swype&lt;/a&gt;, but I was hip with netspeak and I frequently wanted to type non-words like &amp;quot;doge&amp;quot; and &amp;quot;owo&amp;quot; and &amp;quot;~~{@&amp;quot; (it&#39;s a rose!) and so on. Since these non-words aren&#39;t in the dictionary, they won&#39;t be filled in with speech-to-text, and the only way to enter them in Swype is to carefully type each symbol by hand on a miniature qwerty keyboard, again only two inches wide.&lt;/p&gt;
&lt;p&gt;But I had &lt;em&gt;Android&lt;/em&gt;, and back in 2012 you could install anything you wanted on an Android phone, it was awesome! These days it&#39;s a little more locked down unfortunately, you either need a rooted phone or you need to put up with Google&#39;s bullshit. Did you know that you&#39;re &lt;a href=&quot;https://issuetracker.google.com/issues/256669329&quot;&gt;not allowed&lt;/a&gt; to give an app direct access to your Downloads folder anymore? What am I even paying for?&lt;/p&gt;
&lt;p&gt;So! The app I installed was called &lt;a href=&quot;https://en.wikipedia.org/wiki/MessagEase&quot;&gt;MessagEase&lt;/a&gt; and it worked like a charm. It&#39;s got these fat chunky 9 buttons and each one is assigned to about 3 letters, which fits the English alphabet very nicely without the need of autocomplete. It might look small in this screenshot but I assure you back when phone screens were smaller I had that thing zoomed way in, and it fit just fine.&lt;/p&gt;
&lt;p&gt;So like how does it work? Basically, MessagEase is based on &lt;a href=&quot;https://www.exideas.com/ME/ICMI2003Paper.pdf&quot;&gt;this research paper&lt;/a&gt; from 2003 by Saied B. Nesbat of ExIdeas, Inc. The original concept was that this would replace other 9-key typing methods on phones. Instead of a variable-width encoding, MessagEase would use a fixed-width encoding, for faster typing. Instead of the old method, where you had to cycle through 3 or 4 options on each key by pressing it repeatedly, the MessagEase method is set up so that every letter is exactly 2 key-presses. So for instance, the letter &#39;b&#39; would be the center key (5) and then the right edge (6), and you&#39;d remember it as &amp;quot;center-to-right&amp;quot;. With the touchscreen app, you don&#39;t have to remember the numbers because you can just draw the gesture directly! And if you forget the gestures you can just look at the keys, just like on a physical keyboard. It works great!&lt;/p&gt;
&lt;p&gt;MessagEase stopped receiving free updates in February 2024. I&#39;m a little disappointed -- if they&#39;d asked nicely I&#39;d be happy to donate, but I don&#39;t want to be held hostage by closed source software... which is why I&#39;m excited to learn that &lt;a href=&quot;https://f-droid.org/packages/com.dessalines.thumbkey/&quot;&gt;Thumbkey&lt;/a&gt; exists! It&#39;s basically a direct clone, but on f-droid, and it&#39;s fully customizable. The default layout is a bit different, but I changed mine to match the MessagEase layout that I have twelve years of muscle memory with. I highly recommend giving it a try!&lt;/p&gt;
&lt;p&gt;Screens might not be tiny any more but Thumbkey has a second advantage, which is hinted at by the new name: it&#39;s for your thumbs! I&#39;ve found it &lt;em&gt;way&lt;/em&gt; easier to type one-handed on Thumbkey compared to any other on-screen keyboard. Sometimes people ask how I&#39;m able to text so quickly without speech to text, and yep, this is why! I hope they copy this thing for the Steam Deck too. Come on Valve, it&#39;s perfect for your dual touchpads and it would make it way nicer to use chat programs in handheld mode. C&#39;mooooon.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>3DS Browser Compat</title>
    <link href="https://nycki.net/blog/2024-10-08-01-3ds-browser-compat/" />
    <updated>2024-10-08T00:00:00Z</updated>
    <id>https://nycki.net/blog/2024-10-08-01-3ds-browser-compat/</id>
    <content type="html">&lt;p&gt;This site is now compatible with &lt;a href=&quot;https://www.3dbrew.org/wiki/Internet_Browser&quot;&gt;Internet Browser for the New Nintendo 3DS&lt;/a&gt;! Here&#39;s how I did it.&lt;/p&gt;
&lt;p&gt;EDIT 2025-04-14: better solution by Kooda &lt;a href=&quot;https://palmure.fr/blog.html#default-https-but-only-for-recent-browsers&quot;&gt;here&lt;/a&gt; that works for any old browser instead of whitelisting a specific one!&lt;/p&gt;
&lt;h2 id=&quot;disable-https-redirect-for-3ds-agent-string&quot; tabindex=&quot;-1&quot;&gt;Disable HTTPS Redirect for 3DS Agent String &lt;a class=&quot;header-anchor&quot; href=&quot;https://nycki.net/blog/2024-10-08-01-3ds-browser-compat/#disable-https-redirect-for-3ds-agent-string&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The 3DS isn&#39;t able to use HTTPS for most certificates, and there isn&#39;t currently a hack to circumvent this. So, if the user claims to be a 3DS, this site will fall back on HTTP. Otherwise, it will redirect to HTTPS. Here&#39;s how I set up the redirect exception:&lt;/p&gt;
&lt;pre class=&quot;language-httpd&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-httpd&quot;&gt;BrowserMatch &quot;New Nintendo 3DS&quot; allow_http=true
RewriteEngine on
RewriteCond %{ENV:allow_http} &quot;!=true&quot;
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Yes, I could have used &lt;code&gt;%{HTTP_USER_AGENT}&lt;/code&gt; directly in the &lt;a href=&quot;https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#rewritecond&quot;&gt;RewriteCond&lt;/a&gt;, but setting a variable makes it easier to add more exceptions later, if I have some other ancient device that I want to make an exception for.&lt;/p&gt;
&lt;h2 id=&quot;use-css2-and-below&quot; tabindex=&quot;-1&quot;&gt;Use CSS2 And Below &lt;a class=&quot;header-anchor&quot; href=&quot;https://nycki.net/blog/2024-10-08-01-3ds-browser-compat/#use-css2-and-below&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The 3DS browser &lt;a href=&quot;https://en-americas-support.nintendo.com/app/answers/detail/a_id/13802/~/nintendo-3ds-internet-browser-specs&quot;&gt;officially&lt;/a&gt; supports CSS 1, 2, and &amp;quot;some&amp;quot; of 3. My experience is that, if a feature is exclusive to CSS3, you should assume it doesn&#39;t work. In particular, there are no pseudo-elements like &lt;code&gt;:root&lt;/code&gt;, no advanced selectors like &lt;code&gt;:not()&lt;/code&gt;, and &lt;em&gt;no variables&lt;/em&gt;, so I can&#39;t do &lt;code&gt;var(--border-color)&lt;/code&gt; or anything like that.&lt;/p&gt;
&lt;p&gt;Right now I&#39;m content to just let those rules fail, since they seem to be failing gracefully... but later I&#39;ll want to make an alternate stylesheet specifically for the 3DS browser.&lt;/p&gt;
&lt;p&gt;If this helped, you, leave a comment or email me! I appreciate the feedback :)&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Substitutions</title>
    <link href="https://nycki.net/blog/2024-10-03-01-substitutions/" />
    <updated>2024-10-03T00:00:00Z</updated>
    <id>https://nycki.net/blog/2024-10-03-01-substitutions/</id>
    <content type="html">&lt;p&gt;Im makin a minecraft modpack and its gonna have a bunch of cool substitute recipes for stuff that I dont like getting normally. I thought some of these were kinda funny so here you go.&lt;/p&gt;
&lt;p&gt;all images made with &lt;a href=&quot;https://misode.github.io/recipe/&quot;&gt;Recipe Generator&lt;/a&gt; by Misode.&lt;/p&gt;
&lt;h2 id=&quot;you-know-what-screw-the-nether&quot; tabindex=&quot;-1&quot;&gt;you know what screw the nether &lt;a class=&quot;header-anchor&quot; href=&quot;https://nycki.net/blog/2024-10-03-01-substitutions/#you-know-what-screw-the-nether&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;lava bones&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://nycki.net/a/mc-recipe-lava-rod.png&quot; alt=&quot;bone + lava = blaze rod&quot;&gt;&lt;/p&gt;
&lt;p&gt;moldy beans&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://nycki.net/a/mc-recipe-moldy-beans.png&quot; alt=&quot;cocoa beans + red mushroom = netherwart&quot;&gt;&lt;/p&gt;
&lt;p&gt;bloody soil&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://nycki.net/a/mc-recipe-bloody-soil.png&quot; alt=&quot;rotten flesh + dirt = netherrack&quot;&gt;&lt;/p&gt;
&lt;p&gt;refined quartz&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://nycki.net/a/mc-recipe-refined-quartz.png&quot; alt=&quot;purple hat&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://nycki.net/a/mc-recipe-more-diorite.png&quot; alt=&quot;purple hat&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;we-have-end-city-at-home&quot; tabindex=&quot;-1&quot;&gt;we have end city at home &lt;a class=&quot;header-anchor&quot; href=&quot;https://nycki.net/blog/2024-10-03-01-substitutions/#we-have-end-city-at-home&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;purple hat&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://nycki.net/a/mc-recipe-purple-hat.png&quot; alt=&quot;iron hat + magenta dye = shulker shell&quot;&gt;&lt;/p&gt;
&lt;p&gt;icarus&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://nycki.net/a/mc-recipe-icarus.png&quot; alt=&quot;feathers + wax = elytra&quot;&gt;&lt;/p&gt;
&lt;p&gt;portal flower&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://nycki.net/a/mc-recipe-portal-flower.png&quot; alt=&quot;ender pearl + cherry sapling = chorus flower&quot;&gt;&lt;/p&gt;
&lt;p&gt;moon rocks&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://nycki.net/a/mc-recipe-moon-rocks.png&quot; alt=&quot;ender pearl + sandstone = end stone&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;this-one-just-feels-nice-thematically&quot; tabindex=&quot;-1&quot;&gt;this one just feels nice thematically &lt;a class=&quot;header-anchor&quot; href=&quot;https://nycki.net/blog/2024-10-03-01-substitutions/#this-one-just-feels-nice-thematically&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;crystal music&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://nycki.net/a/mc-recipe-crystal-music.png&quot; alt=&quot;planks + amethyst shard = note block&quot;&gt;&lt;/p&gt;
&lt;p&gt;thanks for coming to my minecraft live&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Chost</title>
    <link href="https://nycki.net/blog/2024-09-21-02-chost/" />
    <updated>2024-09-21T00:00:00Z</updated>
    <id>https://nycki.net/blog/2024-09-21-02-chost/</id>
    <content type="html">&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://cohost.org/nycki/post/5797045-toki-pona-is-esperan&quot;&gt;originally posted 2024-05-01 on Cohost.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;toki pona is esperanto for people whose myst was baba is you&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>ethics of reuploading</title>
    <link href="https://nycki.net/blog/2024-09-21-01-ethics-of-reuploading/" />
    <updated>2024-09-21T00:00:00Z</updated>
    <id>https://nycki.net/blog/2024-09-21-01-ethics-of-reuploading/</id>
    <content type="html">&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://cohost.org/nycki/post/7382191-ethics-of-reuploadin&quot;&gt;originally posted 2024-08-24 on cohost.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;so like... I think we can all agree that Downloading Is Good, right? if you see something you like online, save a copy, because it might not be there tomorrow.&lt;/p&gt;
&lt;p&gt;so... how do we feel about Reuploading Is Good? if you save something, and then it goes offline, then you should re-upload it... right?&lt;/p&gt;
&lt;h2 id=&quot;caveat-1-consent&quot; tabindex=&quot;-1&quot;&gt;Caveat 1: Consent &lt;a class=&quot;header-anchor&quot; href=&quot;https://nycki.net/blog/2024-09-21-01-ethics-of-reuploading/#caveat-1-consent&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If the artist doesn&#39;t want something to be public, we should respect their wishes. But, unless the work is posted with an explicit License Agreement (addendum: or any other message of author intent), we sort of have to infer what those wishes are, right?&lt;/p&gt;
&lt;p&gt;I would assume that when a creator first posts something publically, that&#39;s granting consent, and if they explicitly remove their own work, or post it behind a paywall, that&#39;s revoking consent.&lt;/p&gt;
&lt;p&gt;So, for instance, if someone posted their work on Furaffinity, and then Furaffinity happened to go dark for an indeterminate period of time, they would have granted consent but never revoked it, so re-uploading would be ethical. Of course an artist can always explicitly grant or revoke consent as well.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;caveat-2-death-of-the-artist&quot; tabindex=&quot;-1&quot;&gt;Caveat 2: Death of the Artist &lt;a class=&quot;header-anchor&quot; href=&quot;https://nycki.net/blog/2024-09-21-01-ethics-of-reuploading/#caveat-2-death-of-the-artist&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If an artist dies, or otherwise disappears for an extended period of time, should we assume their work now &amp;quot;belongs to the public&amp;quot; and is safe to post? This isn&#39;t about the legality, because copyright law is not universal and, at least in the USA, copyright law is pretty obviously unethical.&lt;/p&gt;
&lt;p&gt;I would argue that it&#39;s ethical to reupload work if the creator has died or disappeared for more than, let&#39;s say seven years. A long time, for sure, but not an eternity, and long enough that if they were just on a haitus they have plenty of time to come back and make their wishes more explicitly clear.&lt;/p&gt;
&lt;p&gt;Hot take: I believe this &lt;em&gt;also&lt;/em&gt; applies to paywalled content, or at least paywalled content that can no longer be purchased. Nothing should be locked up forever, especially if nobody&#39;s benefiting from it being locked up.&lt;/p&gt;
&lt;h2 id=&quot;caveat-3-edits-generative-ai-and-respect-for-the-dead&quot; tabindex=&quot;-1&quot;&gt;Caveat 3: Edits, Generative AI, and Respect for the Dead &lt;a class=&quot;header-anchor&quot; href=&quot;https://nycki.net/blog/2024-09-21-01-ethics-of-reuploading/#caveat-3-edits-generative-ai-and-respect-for-the-dead&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Consent to share work in its current form, whether explicit or implied, is &lt;em&gt;not&lt;/em&gt; the same as consent to edit a work, feed it to a machine learning model, or otherwise profit off of it. It is never ethical to share someone else&#39;s work without attribution and it is rarely ethical to share edits.&lt;/p&gt;
&lt;h2 id=&quot;caveat-4-remixing-and-sampling&quot; tabindex=&quot;-1&quot;&gt;Caveat 4: Remixing and Sampling &lt;a class=&quot;header-anchor&quot; href=&quot;https://nycki.net/blog/2024-09-21-01-ethics-of-reuploading/#caveat-4-remixing-and-sampling&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If a work has been public for a long time, again let&#39;s say seven years or more, then it should absolutely be ethical to edit and remix it, as long as you give proper attribution and there&#39;s no explicit requests to the contrary. I&#39;m not sure why I feel so strongly about this caveat but it just feels wrong to say &amp;quot;oh yeah this art is sacred, you can look but don&#39;t touch, and if you make a copy then all you can do with the copy is look and not touch, forever.&amp;quot;&lt;/p&gt;
&lt;h2 id=&quot;caveat-5-disobedience&quot; tabindex=&quot;-1&quot;&gt;Caveat 5: Disobedience &lt;a class=&quot;header-anchor&quot; href=&quot;https://nycki.net/blog/2024-09-21-01-ethics-of-reuploading/#caveat-5-disobedience&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;An artist&#39;s wishes should be respected whenever reasonable, even after their death or disappearance. Wishes like &amp;quot;don&#39;t draw porn of my sona&amp;quot;, for instance, should be respected even if the creator turned out to be a nazi or whatever, it&#39;s still just common courtesy. However, not all requests should be taken as reasonable. If someone tried to claim that they own the concept of &#39;characters with CRT monitors for heads&#39; and that it&#39;s a Closed Species, that would not be a reasonable request.&lt;/p&gt;
&lt;p&gt;These should be taken on a case-by-case basis because I don&#39;t think I could possibly draw an umbrella large enough to cover when I consider disobedience to be ethical, but it&#39;s definitely not never.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I&#39;m happy to hear counterpoints to any of these caveats by the way, this is just my gut instinct on what&#39;s &amp;quot;ethical&amp;quot; and what&#39;s not -- if I&#39;ve missed something important then let me know!&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;addendum-1-nothing-is-eternal&quot; tabindex=&quot;-1&quot;&gt;Addendum 1: Nothing is Eternal &lt;a class=&quot;header-anchor&quot; href=&quot;https://nycki.net/blog/2024-09-21-01-ethics-of-reuploading/#addendum-1-nothing-is-eternal&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I&#39;ve gotten some pushback like &amp;quot;what if seven years isn&#39;t long enough for Death of the Artist to apply&amp;quot;, and that&#39;s a great point! Sometimes it takes a lot longer than that. I&#39;m not attempting to put an exact timeline on how long an artist&#39;s wishes should be respected, but I &lt;em&gt;am&lt;/em&gt; attempting to argue that such a timeline &lt;em&gt;exists&lt;/em&gt; and it&#39;s &lt;em&gt;not infinite.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;addendum-2-corporations-are-not-people&quot; tabindex=&quot;-1&quot;&gt;Addendum 2: Corporations Are Not People &lt;a class=&quot;header-anchor&quot; href=&quot;https://nycki.net/blog/2024-09-21-01-ethics-of-reuploading/#addendum-2-corporations-are-not-people&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Part of the motivation behind this essay is the idea that I think it&#39;s ethical to repost a 40-year old rom file but not ethical to repost a 2-week old patreon exclusive, and I think part of that comes down to consent and time. But there&#39;s another very obvious factor I should have considered, which is money! I think it &lt;em&gt;absolutely&lt;/em&gt; makes a difference. If someone is making a living on the royalties of something they published 20+ years ago and they&#39;re not a huge corporation that can afford lobbyists and lawyers, then reposting does direct measurable harm, and is therefore less ethical.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Comic Template</title>
    <link href="https://nycki.net/blog/2024-09-18-01-comic-template/" />
    <updated>2024-09-18T00:00:00Z</updated>
    <id>https://nycki.net/blog/2024-09-18-01-comic-template/</id>
    <content type="html">&lt;p&gt;I wrote a &lt;a href=&quot;https://github.com/nycki93/11ty-comic&quot;&gt;site template&lt;/a&gt; for webcomics. It has the absolute bare minimum amount of html, css, and templating, because I figure if you&#39;re making a comic you probably want to do that stuff yourself! I might use it myself at some point, I used to write &lt;a href=&quot;https://mspfa.com/?s=19&quot;&gt;an adventure comic&lt;/a&gt;...&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Comments!</title>
    <link href="https://nycki.net/blog/2024-09-17-01-comments/" />
    <updated>2024-09-17T00:00:00Z</updated>
    <id>https://nycki.net/blog/2024-09-17-01-comments/</id>
    <content type="html">&lt;p&gt;I got it working! For now at least. Comments are hosted on my own private server using &lt;a href=&quot;https://docs.comentario.app/&quot;&gt;Comentario&lt;/a&gt;. I don&#39;t feel like doing a full writeup right now but uhhhhh I&#39;ll just dump my config files, maybe it&#39;ll help you set this up someday&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# docker-compose.yml&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;3&#39;&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; registry.gitlab.com/comentario/comentario&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;dev&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;4e35a801
    &lt;span class=&quot;token key atrule&quot;&gt;network_mode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; host
    &lt;span class=&quot;token key atrule&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;PORT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8300&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;BASE_URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; https&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//xnil.io/comentario
      &lt;span class=&quot;token key atrule&quot;&gt;SECRETS_FILE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; /secrets.yaml
    &lt;span class=&quot;token key atrule&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; ./secrets.yaml&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;/secrets.yaml&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;ro
    &lt;span class=&quot;token key atrule&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; /comentario/comentario &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;v
    &lt;span class=&quot;token key atrule&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; unless&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;stopped&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-xml&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;VirtualHost&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;*:&lt;/span&gt;80&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

ServerName xnil.io
RewriteEngine on
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;VirtualHost&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;*:&lt;/span&gt;443&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

ServerName xnil.io
DocumentRoot /data/xnil.io/site
ErrorDocument 404 /404.html

ProxyPreserveHost On
ProxyPass /comentario http://localhost:8300/comentario
ProxyPassReverse /comentario http://localhost:8300/comentario

&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Directory&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
  Options FollowSymLinks MultiViews
  Require all granted
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;Directory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;

Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/xnil.io/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/xnil.io/privkey.pem
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I had to read this like four times to make sure it wasn&#39;t gonna leak anything but I&#39;m pretty sure all the actual important stuff is in the secrets file. Good job Comentario.&lt;/p&gt;
&lt;p&gt;Oh yeah also I had to google a bunch of commands to hack together a postgres server. That&#39;s why I have network-mode host set in the docker. If you can get a container to talk to the bridged network some other way then let me know. In the comments! Or send me an email lol.&lt;/p&gt;
&lt;p&gt;ok bye!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>The Cohorst</title>
    <link href="https://nycki.net/blog/2024-09-15-01-the-cohorst/" />
    <updated>2024-09-15T00:00:00Z</updated>
    <id>https://nycki.net/blog/2024-09-15-01-the-cohorst/</id>
    <content type="html">&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://cohost.org/nycki/post/7735017-the-cohorst&quot;&gt;cross-posted from Cohost&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I don&#39;t think we&#39;re going to ever have a true &amp;quot;successor&amp;quot; to Cohost, and I don&#39;t think we should! I think we should look at this more like &lt;a href=&quot;https://en.wikipedia.org/wiki/Lucasfilm_Games#Legacy&quot;&gt;The LucasArts Breakup&lt;/a&gt; which resulted in Doublefine, Telltale, and a handful of smaller indie teams, each one led by an alumni of the previous team.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mynotaurus&lt;/strong&gt; has already stepped up with &lt;a href=&quot;https://floofy.tech/@mynotaurus&quot;&gt;an active Mastodon&lt;/a&gt; and &lt;a href=&quot;https://zatzhing.me/webring&quot;&gt;The Enclave Webring&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Smutteo&lt;/strong&gt; has put together &lt;a href=&quot;https://bsky.app/profile/smutteo.bsky.social/post/3l3qzrrkd622p&quot;&gt;The NSFW Cohost Starter Pack&lt;/a&gt; on Bsky&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cania&lt;/strong&gt; has written a &lt;a href=&quot;https://cania.neocities.org/blog/how-to-use-publii-to-make-a-blog-on-neocities-without-writing-html-and-minimal-css&quot;&gt;quick start guide&lt;/a&gt; for how to make a blog on Neocities or similar (try Nekoweb)!&lt;/li&gt;
&lt;li&gt;A bunch of other artists have moved to private Discord groups for the time being, some of them are also starting personal homepages.&lt;/li&gt;
&lt;li&gt;If you know someone else who&#39;s stepped into the community organizer role then let me know! Maybe I&#39;ll make a Cohost Legacy article like that LucasArts Legacy section on Wikipedia.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&#39;s up to us to step up as moderators of our own communities. We should absolutely reach out to other members of the Cohost cohort (the &lt;strong&gt;Cohorst&lt;/strong&gt;) for help, but ultimately I think the community is going to split and go several different ways.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Chost</title>
    <link href="https://nycki.net/blog/2024-09-13-03-chost/" />
    <updated>2024-09-13T00:00:00Z</updated>
    <id>https://nycki.net/blog/2024-09-13-03-chost/</id>
    <content type="html">&lt;p&gt;There are only two settings on every dryer: &amp;quot;maximum&amp;quot; and &amp;quot;who cares&amp;quot;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Phposting</title>
    <link href="https://nycki.net/blog/2024-09-13-02-phposting/" />
    <updated>2024-09-13T00:00:00Z</updated>
    <id>https://nycki.net/blog/2024-09-13-02-phposting/</id>
    <content type="html">&lt;p&gt;Wow, posting on my phone kinda sucks. My current workflow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;pull the blog source files into &lt;strong&gt;termux&lt;/strong&gt; on android with &lt;code&gt;git pull&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;run &lt;code&gt;sshd&lt;/code&gt; in termux so I can access its files as if they were on the network&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;use &lt;strong&gt;cx file explorer&lt;/strong&gt; to view the network drive, upload images, and write a text file (YOU ARE HERE)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://nycki.net/blog/2024-09-13-02-phposting/screenshot.png&quot; alt=&quot;a screenshot of a text editor&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;go back to termux and push the updated files&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;log into my server with &lt;strong&gt;connectbot&lt;/strong&gt; and &lt;code&gt;npm run build&lt;/code&gt; to compile the markdown into html with &lt;strong&gt;eleventy&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;check in &lt;strong&gt;firefox&lt;/strong&gt; to make sure it looks correct&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;this is fine for longer posts like this one but it does make &amp;quot;chosting&amp;quot; somewhat time consuming. Anyone have suggestions for some sort of build automation tool?&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Request For Comments</title>
    <link href="https://nycki.net/blog/2024-09-13-01-request-for-comments/" />
    <updated>2024-09-12T00:00:00Z</updated>
    <id>https://nycki.net/blog/2024-09-13-01-request-for-comments/</id>
    <content type="html">&lt;p&gt;Does anyone have suggestions for comment boxes? I want something similar to &lt;a href=&quot;https://commentbox.io/&quot;&gt;commentbox.io&lt;/a&gt; but without anonymous comments (and I think $20/mo for that privilege alone is a little steep). I&#39;m willing to self-host &lt;a href=&quot;https://schnack.cool/&quot;&gt;schnack&lt;/a&gt; but I was hoping for something I can recommend to other people without them having to self-host it.&lt;/p&gt;
&lt;p&gt;Email me if you have any ideas!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Chost</title>
    <link href="https://nycki.net/blog/2024-09-12-02-chost/" />
    <updated>2024-09-12T00:00:00Z</updated>
    <id>https://nycki.net/blog/2024-09-12-02-chost/</id>
    <content type="html">&lt;p&gt;I put the cracker down first, then the cheese, then the ham.&lt;/p&gt;
&lt;p&gt;that&#39;s my hors d&#39;oeuvre operations.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Hey Cohost</title>
    <link href="https://nycki.net/blog/2024-09-12-01-hey-cohost/" />
    <updated>2024-09-12T00:00:00Z</updated>
    <id>https://nycki.net/blog/2024-09-12-01-hey-cohost/</id>
    <content type="html">&lt;p&gt;Holy shit I&#39;m doing this. I&#39;m... &amp;quot;blogging.&amp;quot;&lt;/p&gt;
&lt;p&gt;I&#39;m using a tool for this called &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;Eleventy&lt;/a&gt;, working from their template called &lt;a href=&quot;https://github.com/11ty/eleventy-base-blog&quot;&gt;eleventy-base-blog&lt;/a&gt;. I&#39;m hosting this on a server I bought from &lt;a href=&quot;https://www.digitalocean.com/&quot;&gt;DigitalOcean&lt;/a&gt; because I can also use it to run Minecraft.&lt;/p&gt;
&lt;p&gt;Look at all those links. Wow. I sure am Posting again.&lt;/p&gt;
</content>
  </entry>
</feed>
