<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Site Feed</title><link>https://0xff.nu</link><description/><language>en</language><lastBuildDate>Tue, 12 May 2026 14:22:32 -0000</lastBuildDate><item><title>Hajime-lqip</title><link>https://0xff.nu/hajime-lqip/</link><description>&lt;p&gt;The idea to implement some kind of LQIP (Low Quality Image Placeholder) came about as part of working on supporting &lt;code&gt;type: image&lt;/code&gt; posts on this here website.&lt;/p&gt;
&lt;p&gt;I didn’t want to deal with generating thumbnails (though in retrospect this would’ve been a simpler approach) nor, of course, make you load the entire size of the image by just browsing the index.&lt;/p&gt;
&lt;p&gt;I read about a similar, albeit much more fucking elaborate approach in a post titled &lt;a href="https://frzi.medium.com/lqip-css-73dc6dda2529"&gt;Image placeholders in pure CSS — or: Defying gods with math and color&lt;/a&gt; .
And so, armed with the idea but having forgotten any and all details about the implementation – I’ve decided to roll my own.&lt;/p&gt;
&lt;h2 id="what-i-need-it-to-do"&gt;What I need it to do&lt;a class="headerlink" href="#what-i-need-it-to-do" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As the general idea is to have an annual photo grid, where each (relatively) tiny square is an &lt;code&gt;image&lt;/code&gt; entry that is processed by Hajime upon generation, it makes sense to generate the LQIP in the same pass.&lt;/p&gt;
&lt;p&gt;Naturally, I prefer a process that is not too heavy or resource intensive, and that doesn’t require creating a bunch of extra static files.&lt;/p&gt;
&lt;div class="admonition warning"&gt;
&lt;p class="admonition-title"&gt;Warning&lt;/p&gt;
&lt;p&gt;The resource usage is TBD in a “yeah I take a photo every single day” (i.e full, 365 image gallery) scenario, but I don’t suspect it to be too resource intensive.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id="how-did-i-do-it"&gt;How did I do it&lt;a class="headerlink" href="#how-did-i-do-it" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The napkin math process I thought of looks like this:
%% Image from remarkable %%&lt;/p&gt;
&lt;p&gt;Having cracked open the pillow docs
 I haven’t used Pillow much, but I knew that’s kinda what I have to go with.&lt;/p&gt;</description><pubDate>Tue, 12 May 2026 14:22:32 -0000</pubDate></item><item><title>260327</title><link>https://0xff.nu/260327/</link><description/><pubDate>Tue, 12 May 2026 14:22:32 -0000</pubDate></item><item><title>ADHD is...</title><link>https://0xff.nu/adhd/</link><description>&lt;p&gt;&lt;img src="/adhd-headache.png" /&gt;
As I go through life, the understanding that some of us are just not... built for the chaotic, clusterfuck of a circus that society pressures the world to become was not only cemented, but also encased in an indestructible material. Every time I hear someone's downplaying, minimizing and trivializing "aren't we all a little bit ADHD?" comment I feel an urge to shake some sense into them.&lt;/p&gt;
&lt;p&gt;Instead of doing that, here's a glimpse into how I experience ADHD.&lt;/p&gt;
&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;p&gt;This post will be updated from time to time.&lt;/p&gt;
&lt;/div&gt;
&lt;h1 id="adhd-is"&gt;ADHD is...&lt;a class="headerlink" href="#adhd-is" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;Your brain making your body physically rebel against sitting down and working – like actually being unable to sit because it's uncomfortable and borderline painful, no matter if you're a textbook, poster boy for ergonomics or a crooked shrimp.&lt;/li&gt;
&lt;li&gt;Remembering the faces of people you were introduced to five years ago, but not their name&lt;/li&gt;
&lt;li&gt;Needing the utmost concentration while preparing meal dividers for your newborn, as your fucking brain just can't count to 6 without thinking about literally anything else.&lt;/li&gt;
&lt;li&gt;Trying to find the most bizarre object on your desk to play with or combine together with a different object to form an ADHD-fuelled megazord because that fucking 30 minute meething turned out to be 1 hour long.&lt;/li&gt;
&lt;li&gt;Creating a whole new fucking HomeAssistant dashboard right fucking NOW instead of toggling a switch because your wife told you that the light in the bathroom didn't turn on.&lt;/li&gt;
&lt;li&gt;Drinking coffee or black tea and going straight to bed, because caffeine doesn’t work on you&lt;/li&gt;
&lt;li&gt;Remembering every single little things about a video game you’ve played over a year ago, yet failing to remember what you’ve had for breakfast two days ago&lt;/li&gt;
&lt;li&gt;Accepting the fact that when you tell people you have ADHD they will just fucking dismiss it, and then get surprised when it manifests itself&lt;/li&gt;
&lt;li&gt;Having tens of unstarted projects in your backlog, because everything is interesting and you &lt;em&gt;want&lt;/em&gt; to do them all, but just don't have enough time&lt;/li&gt;
&lt;li&gt;Having that one drawer meticulously organized, while the rest of your space&lt;/li&gt;
&lt;li&gt;Taking just a few minutes longer in the bathroom just because it’s quiet&lt;/li&gt;
&lt;li&gt;Having a little dance in your head when you were able to do what you set out to do, because having one externally will be misunderstood just because “you did a thing”&lt;/li&gt;
&lt;li&gt;Opening Obsidian to take some notes, only to find yourself half an hour later waist deep into reading about the psychology of color palettes &lt;ol&gt;
&lt;li&gt;For the record, the journey here is: Open Obsidian -&amp;gt; "I think I can tweak the font a bit" -&amp;gt; "but now the colors feel... wrong" -&amp;gt; "why this color works but this one doesn't" -&amp;gt; WHY.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Constantly feeling like you’re being judged for something you cannot control&lt;/li&gt;
&lt;li&gt;Constantly asking yourself if you’re inadequate because society is expecting unrealistic results from you&lt;/li&gt;
&lt;li&gt;Opening iOS Shortcuts every time you go down the elevator just to see if any new actions were added because your brain is not occupied enough on this (not even) one minute long journey&lt;/li&gt;
&lt;/ol&gt;</description><pubDate>Fri, 08 May 2026 00:00:00 -0000</pubDate></item><item><title>AMD GPU Crashes</title><link>https://0xff.nu/amd-garbage/</link><description>&lt;p&gt;My Gigabyte RX6750XT Gaming has been crashing for no apparent reason.&lt;/p&gt;
&lt;div class="admonition warning"&gt;
&lt;p class="admonition-title"&gt;Warning&lt;/p&gt;
&lt;p&gt;I already ran DDU. Twice.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id="2026-05-07"&gt;2026-05-07&lt;a class="headerlink" href="#2026-05-07" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I finally decided to try and investigate this shit further, so I'm making this a public post.
While opening a tab in Obsidian, with no significant GPU load sans LM Studio running in the background with &lt;code&gt;qwen3.5-9b-uncensored-hauhaucs-aggressive&lt;/code&gt; being loaded since yesterday (and I was able to play together with this model running with no issues).&lt;/p&gt;
&lt;p&gt;It started with a hang, with 4/5 of my screen turning gray. A minute after, black screen, driver fallback and I was able to see my desktop again.&lt;/p&gt;
&lt;p&gt;The first harbinger of doom was a window similar to this one, except it said there was a driver "timeout", and while I was filling out the report, that crashed as well and showed me this window.
&lt;img src="/Obsidian_2026-05-07_14-05-01.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;The GPU, of course, is now disabled.
&lt;img src="/CoreKeeper_2026-05-07_14-12-32.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Reliability history doesn't even show the problem:
&lt;img src="/Pasted image 20260507142313.png" /&gt;&lt;/p&gt;
&lt;p&gt;System events however is able to shed some light
&lt;img src="/Pasted image 20260507142550.png" /&gt;&lt;/p&gt;
&lt;p&gt;All three warnings are identical -- &lt;code&gt;Display driver amduw23g-198974-eda2a421 stopped responding and has successfully recovered.&lt;/code&gt;
The two errors above the warnings are &lt;code&gt;The iommu has detected an error.&lt;/code&gt;, and the information item is &lt;code&gt;Process C:\Windows\System32\DriverStore\FileRepository\u0198974.inf_amd64_dcac9659486b668a\B025819\atieclxx.exe (process ID:2984) reset policy scheme from {8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c} to {8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I've decided to filter the logs by &lt;code&gt;(?i)amd.*|D3D.*|Direct3D.*&lt;/code&gt;:
&lt;img src="/Pasted image 20260507143304.png" /&gt;&lt;/p&gt;
&lt;p&gt;These are the messages:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Display driver amduw23g-198974-eda2a421 stopped responding and has successfully recovered.
Display driver amduw23g-198974-eda2a421 stopped responding and has successfully recovered.
Display driver amduw23g-198974-eda2a421 stopped responding and has successfully recovered.
Display driver amduw23g-195698-fece65a5 stopped responding and has successfully recovered.
Display driver amduw23g-195698-fece65a5 stopped responding and has successfully recovered.
Display driver amduw23g-195698-fece65a5 stopped responding and has successfully recovered.
Display driver amduw23g-198281-bc502516 stopped responding and has successfully recovered.
Display driver amduw23g-198281-bc502516 stopped responding and has successfully recovered.
Display driver amduw23g-198281-bc502516 stopped responding and has successfully recovered.
Display driver amduw23g-198281-bc502516 stopped responding and has successfully recovered.
Display driver amduw23g-198281-bc502516 stopped responding and has successfully recovered.
Display driver amduw23g-198281-bc502516 stopped responding and has successfully recovered.
Display driver amduw23g-197639-19a81ed0 stopped responding and has successfully recovered.
Display driver amduw23g-197639-19a81ed0 stopped responding and has successfully recovered.
Display driver amduw23g-197639-19a81ed0 stopped responding and has successfully recovered.
Display driver amduw23g-197639-19a81ed0 stopped responding and has successfully recovered.
Display driver amduw23g-197639-19a81ed0 stopped responding and has successfully recovered.
Display driver amduw23g-196283-af4b12f4 stopped responding and has successfully recovered.
Display driver amduw23g-196283-af4b12f4 stopped responding and has successfully recovered.
Display driver amduw23g-196283-af4b12f4 stopped responding and has successfully recovered.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, driver updates did happen, but the messages are the same otherwise.&lt;/p&gt;
&lt;p&gt;An attempt to disable and re-enable the device via Device Manager results in the same &lt;code&gt;iommu&lt;/code&gt; error:
&lt;img src="/Pasted image 20260507193022.png" /&gt;&lt;/p&gt;</description><pubDate>Thu, 07 May 2026 00:00:00 -0000</pubDate></item><item><title>peek</title><link>https://0xff.nu/peek/</link><description>&lt;div class="admonition warning"&gt;
&lt;p class="admonition-title"&gt;Warning&lt;/p&gt;
&lt;p&gt;&lt;code&gt;peek&lt;/code&gt; was a tool of necessity that was coded with LLM assistance due to lack of time.
This means that bugs are more likely.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Yesterday (2026-03-26) we experienced a power outage, and I realized that I'm a dumbass and that all of my monitoring abilities are inaccessible. The reason being is that Prom-Grafana is located on our NAS while Uptime Kuma is on the RPi together with HomeAssistant, and until everything is loaded I can't access either.&lt;/p&gt;
&lt;p&gt;I was hoping (and trying!) to find a tool similar to &lt;a href="https://github.com/louislam/uptime-kuma"&gt;Uptime Kuma&lt;/a&gt; that works locally via CLI, but I couldn't find anything that does what I needed it to do.&lt;/p&gt;
&lt;p&gt;In true ADHD fashion, I decided to fuck around a little bit and get something quick running locally, but unfortunately, due to the same fucking ADHD and the multitude of other things I want to do and being a dad – I decided to offload the brunt of the work to Mr. Opencode.&lt;/p&gt;
&lt;p&gt;Thus, &lt;code&gt;peek&lt;/code&gt; was born.&lt;/p&gt;
&lt;h2 id="what"&gt;What&lt;a class="headerlink" href="#what" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The focus of &lt;code&gt;peek&lt;/code&gt; was, and is to offer the functionality that I personally needed from it, hence it most definitely is NOT feature complete, but will probably help in a pinch.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;peek&lt;/code&gt; uses YAML syntax for the configuration, which it will try to load from &lt;code&gt;~/.config/peek/config.yaml&lt;/code&gt;. If the path does not exist, &lt;code&gt;peek&lt;/code&gt; will try to initialize it.&lt;/p&gt;
&lt;h3 id="monitor-types"&gt;Monitor Types&lt;a class="headerlink" href="#monitor-types" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ping&lt;/code&gt; – Regular, run of the mill ping&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tcp&lt;/code&gt; - TCP ping using a specific &lt;code&gt;port&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dns&lt;/code&gt; - DNS resolution&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http&lt;/code&gt; – HTTP response code&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="other-features"&gt;Other Features&lt;a class="headerlink" href="#other-features" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Grouping: To make the list easier to filter, you can define &lt;code&gt;groups&lt;/code&gt; and assign &lt;code&gt;target&lt;/code&gt; to them&lt;/li&gt;
&lt;li&gt;Monitor heartbeat frequency configurable via &lt;code&gt;interval&lt;/code&gt;, and &lt;code&gt;timeout&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="installation"&gt;Installation&lt;a class="headerlink" href="#installation" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The recommended way to install &lt;code&gt;peek&lt;/code&gt; is using &lt;code&gt;uv&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-shell"&gt;uv tool install git+https://github.com/hxii/peek.git
&lt;/code&gt;&lt;/pre&gt;</description><pubDate>Fri, 27 Mar 2026 00:00:00 -0000</pubDate></item><item><title>Fields</title><link>https://0xff.nu/20260212/</link><description/><pubDate>Thu, 12 Feb 2026 00:00:00 -0000</pubDate></item><item><title>2025: A Reflection</title><link>https://0xff.nu/end-of-2025/</link><description>&lt;p&gt;2025 is done and dusted, and I'm strolling into 2026 feeling accomplished and happy, but also somewhat nervous, in pain, and unfortunately unemployed. This is my reflection on 2025.&lt;/p&gt;
&lt;div class="toc"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#the-yearly-theme"&gt;The Yearly Theme&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#travel"&gt;Travel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#professional-career"&gt;Professional Career&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#backstory"&gt;Backstory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#analysis"&gt;Analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#job-hunting"&gt;Job Hunting&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#family"&gt;Family&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#health"&gt;Health&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#onwards-to-2026"&gt;Onwards to 2026&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id="the-yearly-theme"&gt;The Yearly Theme&lt;a class="headerlink" href="#the-yearly-theme" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a class="wikilink" href="/yearly-theme-2025"&gt;The yearly theme for 2025&lt;/a&gt; was to Focus, to be short, but as I've mentioned &lt;a class="wikilink" href="/2025-all-the-things"&gt;in my&lt;/a&gt; &lt;a class="wikilink" href="/updates-may-2025"&gt;previous updates&lt;/a&gt; &lt;a class="wikilink" href="/news-2025"&gt;for this year&lt;/a&gt;, things... did not go according to plan.&lt;/p&gt;
&lt;p&gt;So many things happened that focusing—and I mean properly focusing—on anything proved to be quite a fucking challenge, ADHD or not. And even when I was able to take some time to focus and work on one thing at a time, something else would force a context switch, which, as you might know, is just &lt;/p&gt;
&lt;p&gt;&lt;img alt="chefs-kiss" src="/chefs-kiss.png" /&gt;&lt;/p&gt;
&lt;p&gt;Neurotypical people most often fail to understand our struggle. To them, it's just "Why don't you just focus? Look, it's easy! See? Do like this," while intensely staring at the screen, probably thinking I'm just some flavor of stupid that can't fucking comprehend basic instructions.&lt;/p&gt;
&lt;p&gt;For the n-th time—trust me, I fucking tried.&lt;/p&gt;
&lt;h2 id="travel"&gt;Travel&lt;a class="headerlink" href="#travel" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We love traveling and exploring as much as we possibly can, hence we usually prefer to rent a car in order to try and visit or drive through as much as physically possible before we have to board the flight back. Thankfully, we managed to escape our land-locked piece of the smorgasbord (Israel) this year and visit Athens, Greece in February and Italy (by car) in September.&lt;/p&gt;
&lt;h2 id="professional-career"&gt;Professional Career&lt;a class="headerlink" href="#professional-career" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;TL;DR&lt;/p&gt;
&lt;p&gt;In August 2025, I was laid off as R&amp;amp;D Solutions Manager in &lt;a href="https://www.forter.com"&gt;Forter&lt;/a&gt; due to false reasons.&lt;br /&gt;
In September 2025, I started working in &lt;a href="https://usetrmnl.com"&gt;TRMNL&lt;/a&gt; doing support, plugin, and tool development.&lt;br /&gt;
In November 2025, I was laid off from TRMNL, having been told it's not what they thought they needed and that they required more support orientation than development.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Ah yes, arguably the best (read: worst) part of the past year. You're more than welcome to skip this section, as it will be heavy.&lt;/p&gt;
&lt;p&gt;I have no shame in admitting that I am currently unemployed. And why the fuck would I feel ashamed? That would imply that I did something shameful. I did not choose this, nor did I commit some mortal fucking sin that I knew would get me thrown out the fucking door.&lt;/p&gt;
&lt;p&gt;Moreover—I don't want to paint the same false picture that all the fucking influencers would like you to believe. It's not all success. Sometimes you fall. Sometimes you fall hard.&lt;/p&gt;
&lt;h3 id="backstory"&gt;Backstory&lt;a class="headerlink" href="#backstory" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;On July 7th, I had my performance review, during which I received both good and bad feedback. Some of the latter was unwarranted, and I made sure to voice my opinion, which even then I felt was disregarded. And yet, I accepted the feedback and took quite drastic measures to address it.&lt;/p&gt;
&lt;p&gt;Lo and fucking behold—July 15th, I was told by my direct manager that I was invited to a hearing. Yes, you read that fucking right—just 6 fucking work days after the performance review! The timing, to me, just screams this was premeditated. I admit and accept my share—maybe one reason from those given in the invitation was valid, with the rest composed of speculative and subjective opinion rather than fact. Definitely not enough to just throw me out to the fucking wolves, if you ask me.&lt;/p&gt;
&lt;p&gt;Feeling some non-kosher fuckery afoot, I put on my big boy pants and composed a &amp;gt;3000-word document addressing each and every point. I don't live in an echo chamber; I admit fault where I know I fucked up. But just to make sure I wasn't being delusional, I consulted a couple of HR professionals who said the reasons looked like pretext. Fuck me.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;"You are largely absent from the office and have little contact with the team outside of dailies. The lack of physical presence hurts your personal connections with the team[...]"&lt;/li&gt;
&lt;li&gt;"[...]Your technical participation in the team is limited to working on a few projects you choose."&lt;/li&gt;
&lt;li&gt;"Your message to the team is still that work should be done on an individual basis. This does not work for all team members, and hurts work distribution and team member growth."&lt;/li&gt;
&lt;li&gt;"Your personal growth is limited, with only a small project currently underway. The standards you set affect other team members’ performance."&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;During the entirety of my fucking tenure, “You’re not doing enough” was never an argument; “management wants to see you in the office” was. I've had numerous talks with my team, and while I received other feedback from them, they never complained about my physical presence or my allegedly "terrible communication."&lt;/p&gt;
&lt;p&gt;Well, since this is already a fucking circus, might as well entertain everyone—so I brought my pregnant wife with me to be my witness.&lt;/p&gt;
&lt;p&gt;The hearing was, of course, pointless. These hearings are conducted because they're most likely legally required, and me being "given the opportunity to present your position with respect to the subject matter of this hearing" changes nothing—as if the COMPANY™ wants me out, this will not stop them. But it was important to me to make myself heard regardless, to fucking reinforce to them that even if they're firing me, I have my integrity and that I stand behind my choices, actions, and opinions. And to let my direct manager know he's full of shit, and that "I'd rather be a terrible manager than a good boss" (direct quote from what I said).&lt;/p&gt;
&lt;p&gt;Coffin, meet nail.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;"[...]fostering a collaborative environment have not met our expectations. These ongoing issues have negatively impacted the team's overall productivity and cohesion over an extended period."&lt;/li&gt;
&lt;li&gt;"Your role as a manager requires more than individual output; it demands the effective leadership and development of your team. The sustained feedback regarding your limited team contact and an individualistic approach to work indicates a fundamental misalignment with Forter's standards for team leadership and collective growth."&lt;/li&gt;
&lt;li&gt;"While we value your past individual contributions, this decision is based on a sustained lack of effectiveness in your managerial capacity. Your limited presence in the office and individualistic work style suggests that a PIP or role change at this stage would not effectively address the fundamental gaps in your current role."&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Never throughout my fucking tenure did I tell people how to work. I kept saying that people in general, and my team in particular should find a way that works best for them. I also had daily and weekly meetings, and giving them the choice to have ad-hoc meetings IF THEY WANTED TO (I value people's time, and I hate having pointless meetings for the sake of having a meeting).&lt;/p&gt;
&lt;p&gt;And just like that—I was out. An emotional knee-jerk response made me briefly consider suing them, but if we're being honest—what would that change? Would hitting a tree branch heal the rotting tree? Would it change the outcome? Would they suddenly go "fuck, we're dumbasses, he caught us"?&lt;/p&gt;
&lt;p&gt;&lt;img alt="totally premeditated firing" src="/premeditated_yeeting.png" /&gt;&lt;/p&gt;
&lt;p&gt;I'm not saying the entire company is responsible for this, but the fact that this level of poppycock was allowed to occur doesn't instill any level of certainty in me. It's a shame, really. I enjoyed working at Forter.&lt;/p&gt;
&lt;h3 id="analysis"&gt;Analysis&lt;a class="headerlink" href="#analysis" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;“Never explain yourself to people committed to misunderstanding you”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Does it suck? Yes. Was this unjust? Fuck yes. Is it unfair? ...No, not really. 
Fairness would imply that I'm owed something by the &lt;em&gt;universe&lt;/em&gt;. None of us are inherently owed anything. The universe is balanced; it is humans that are unfair, and we can't fault them for it. So it's exactly what this is—just a little man flexing his "boss" muscle by doing his best to get rid of the only actual obstacle standing in front of disbanding the team I put lots of effort into (which is EXACTLY what happened later), who outright refused to say the truth to my face, or the long-reaching hand of corporate was so tightly squeezed that when he was told to jump, all he did was ask "how high."&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Whoever does wrong, wrongs himself; whoever does injustice, does it to himself, making himself evil.”&lt;br /&gt;
&lt;em&gt;– Marcus Aurelius&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Looking back, there probably were some things that I could consider red flags, but there was nothing—and I mean NOTHING—that would even suggest my employment was at stake. The rushed decision just cements the fact that the entire thing was carefully planned.&lt;/p&gt;
&lt;p&gt;Among the many things Stoicism teaches us, one applies here—don't hold grudges. Staying angry is easy, but it will get me nowhere, nor will it change a damn thing about the past. Anger will eat &lt;em&gt;you&lt;/em&gt; from the inside, not the target. So no, Mr. Bossman, I'm not angry at you, just highly disappointed. I'm disappointed that the person that I should, technically speaking, look up to failed to provide a good example.&lt;/p&gt;
&lt;p&gt;I was resilient; I knew where my values lie and I stood by them, and I will continue to do so.&lt;/p&gt;
&lt;p&gt;I never signed up to be anyone's nanny. I value people's time. I do my best to help, but can only address what I see and know, otherwise I communicate that I trust people's ability to tell me there's a problem when they have one. I know my strengths and weaknesses, and I trust other people to know theirs. I know where I fucked up, and I fucking know where I was good, even at the expense of my health.&lt;/p&gt;
&lt;p&gt;It's time you fucking woke up, Forter. At least I was honest.&lt;/p&gt;
&lt;p&gt;And if any company is reading this and thinks "why should we employ this guy? He's going to slander us"—don't do shady shit, and don't employ people who do shady shit, and we're all gonna get along just fine.&lt;/p&gt;
&lt;h3 id="job-hunting"&gt;Job Hunting&lt;a class="headerlink" href="#job-hunting" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;So now, after the thing with TRMNL did not work out, I find myself trying to find a job, again. Who knows—maybe this time around I will find a place that will accept me as I am and what I can build, instead of &lt;img alt="surprised pikachu" class="inline" src="/surprised-pikachu.png" /&gt; when trying to shape me, against my will, into something I'm not or force me to change my values.&lt;/p&gt;
&lt;p&gt;I might be wrong, of course, but in my humble opinion, I'm not asking for much—to be able to make a difference and contribute by doing what I like and am good at, while being paid a decent wage, in a way that's comfortable for me and doesn't require me to make a choice between family and work, in a company I can grow together with.&lt;/p&gt;
&lt;p&gt;I'm not asking to be paid to do nothing, nor do I want to be paid millions, nor do I want to take advantage of one company or another.&lt;/p&gt;
&lt;p&gt;In practice though, it looks like the local job market is extra difficult right now, even if you pretend for a second to not have &lt;em&gt;any&lt;/em&gt; kind of preferences about where it is you're applying. Does me having preferences and values make me a pariah? I’d like to believe it doesn’t, but I have a hunch that the market is SO broken that companies are absolutely sure they hold ALL the cards and that we should be thankful for whatever they do offer to candidates.&lt;/p&gt;
&lt;p&gt;There however comes a point where you just refuse to play THEIR games according to their rules. Could it create a situation where it makes most kids on your street think you’re that one weird kid so they paint you as an outcast and refuse to play hide and seek with you? Maybe, but maybe that “isolation” is exactly what you need to find your &lt;em&gt;true&lt;/em&gt; friends.&lt;/p&gt;
&lt;p&gt;That being said, I’m not deaf nor blind—it seems like the demand for my "profession" is in decline. Can I pursue my other passion? Yes, but learning and pivoting takes time, and right now I feel like someone lit a fire under my ass. I'm being pressured to jump into the fucking deep end of the pool before I can get my goggles on.&lt;/p&gt;
&lt;p&gt;React will take time, as will Swift/SwiftUI, but even if I could expedite the process, I wouldn't feel comfortable enough to plaster it on my CV and apply to jobs that require them.&lt;/p&gt;
&lt;p&gt;Am I scared? To an extent—yes. Nobody wants to be uncertain about their own employment, but I try to live by the saying:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“I never think of the future, it comes soon enough.”&lt;br /&gt;
&lt;em&gt;– Albert Einstein&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Or, if we travel a bit further back in time:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“True happiness is to enjoy the present without anxious dependence upon the future, not to amuse ourselves with either hopes or fears but to rest satisfied, for he that wants nothing. The greatest blessings of mankind are within us and within our reach. A wise man is content with his lot, whatever it may be, without wishing for what he has not.”&lt;br /&gt;
&lt;em&gt;– Seneca&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So far, for this specific job hunt, I've amassed 46 generic fucking rejection emails, one questionable. I've tried asking for actual feedback by replying to those emails that did not come from some "noreply" address, and have heard nothing. So companies want good candidates but refuse to provide any fucking feedback that can explain the fucking arbitrary "good" level, even if according to the description I theoretically tick all the boxes.&lt;/p&gt;
&lt;p&gt;What if I fucking pretend I'm fine with commuting to TLV every single day? So now recruiters micro-question "Really? Are you sure? Are you double sure? You're saying yes, but we think you mean no. Oh, you've done it before? What, every day? Yah well, you're rejected anyways."&lt;/p&gt;
&lt;p&gt;We want you in the office. You can't work remotely because... reasons. But hey, we're hybrid—you can ENJOY THE COMFORT OF NOT USING THE PUBLIC TRANSPORT, Woooooo! But you can't live too far away.&lt;/p&gt;
&lt;p&gt;&lt;img alt="wat" src="/wat.png" /&gt;&lt;/p&gt;
&lt;p&gt;I’m not saying I'm holding some kind of higher moral ground here, but I’ve definitely got my reaffirmation that I’m playing the correct game by valuing the things that are, in my opinion, the important ones instead of succumbing to the will of those who allegedly hold the cards.&lt;/p&gt;
&lt;p&gt;The house always wins? Not if you don’t enter the fucking casino.&lt;/p&gt;
&lt;p&gt;I’m doing the best I currently can, while keeping my sanity intact, paying more attention to my health (more on that later), and making sure to enjoy whatever extra precious time I’ve been gifted to be with my family, instead of running a fucking marathon on someone else's hedonistic treadmill.&lt;/p&gt;
&lt;h2 id="family"&gt;Family&lt;a class="headerlink" href="#family" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Our second son was born in October. I was actually low-key stressed about the whole process, given the previous, quite traumatic childbirth my wife had to go through. Thankfully though, I actually managed to hold back and fight off that tiny, creeping sense of panic that was trying to burrow its way in.&lt;/p&gt;
&lt;p&gt;Not only that, but this time around I got to accompany my wife to the operating room and greet our meowing little kitten of a baby into the world, instead of being left alone in a room by myself for three hours after my wife was rushed to an operating room by a team of twenty people.&lt;/p&gt;
&lt;p&gt;While I'm familiar with the technicalities, the things I need to buy, hell, even the exhaustion I'm experiencing, it's definitely more challenging than I expected this time around, in part because our firstborn—who is about to turn six—requires extra attention, being on the spectrum and whatnot.&lt;/p&gt;
&lt;p&gt;But having been able to work remotely (while I was working, that is) definitely had a major, positive impact on me being able to spend more time with the wife and kids doing fun things together.&lt;/p&gt;
&lt;p&gt;See, I never thought of myself as a family man prior to having kids, but then Andrew was born and I began to understand where my priorities lie, and now with little Kaito joining the team I know for a fucking fact that family comes first. Work is replaceable; family is not. Remember this.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In 20 years' time, the only people who will remember that you worked late are your kids.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Or, here's one that digs a little deeper:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The graveyards are full of people the world could not do without.&lt;br /&gt;
&lt;em&gt;– Elbert Hubbard&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="health"&gt;Health&lt;a class="headerlink" href="#health" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Health is a fickle thing—you're healthy until you're not. While I started paying more and more attention to both my physical health and mental wellbeing over the past year, in retrospect my time in Forter was full of needless stress, despite the fact I mostly worked remotely, was doing—to the best of my abilities—what I like, and making sure I had time in the morning for exercise.&lt;/p&gt;
&lt;p&gt;And it now looks like I'm paying the price, having been recently diagnosed with CSR&lt;sup id="fnref:2-1"&gt;&lt;a class="footnote-ref" href="#fn:2-1"&gt;1&lt;/a&gt;&lt;/sup&gt;, which apparently is caused by black magic and planet misalignment, as nobody fucking knows exactly what causes it, with the closest common thing medicine agrees upon being stress.&lt;/p&gt;
&lt;p&gt;If that wasn't enough, I am also now dealing with and trying to diagnose high blood pressure that started making itself known around May 2025, but I wasn't paying attention to it. The symptoms for me are mostly headaches, although sometimes it might make me feel generally shitty.&lt;/p&gt;
&lt;p&gt;At some point in November, I got to my lowest point. I'm not comparing my pain and discomfort to others, but that evening I just wanted to... shut down.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Intense left leg/lower back pain (pinched nerve)&lt;/li&gt;
&lt;li&gt;Blocked ears (gotta visit EMT to fix 'em periodically); tinnitus&lt;/li&gt;
&lt;li&gt;Bad central field of vision because CSR (worse in dark)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It was too much. Even for me.&lt;/p&gt;
&lt;p&gt;&lt;img alt="my body is pain" src="/broken_body.png" /&gt;&lt;/p&gt;
&lt;p&gt;All in all, the second part of 2025 turned out to be difficult, especially since in an effort to reduce physical stress, I also had to cut down on exercise.&lt;/p&gt;
&lt;p&gt;Considering that work is the only meaningful and constant stressor in my life, I have nothing else to point my fucking finger at but my experience at Forter. I put too much effort in, it seems, at the expense of my own wellbeing.&lt;/p&gt;
&lt;h2 id="onwards-to-2026"&gt;Onwards to 2026&lt;a class="headerlink" href="#onwards-to-2026" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I start 2026 then not with a new book, but a new page in the same book. It's important for the context to remain intact and to wear your past experience as armor and a compass to help shape my decisions going forward.&lt;/p&gt;
&lt;p&gt;2025 ended with discomfort, but life is not about being comfortable. You can't become stronger or wiser when you're comfortable.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“It's not because things are difficult that we dare not venture. It's because we dare not venture that they are difficult.”&lt;br /&gt;
&lt;em&gt;– Seneca&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And so, in 2026 I want to focus on regaining the balance that was lost. I also want to make sure I practice two more things that I historically have been bad at:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Asking for help&lt;/li&gt;
&lt;li&gt;Saying no&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you, dear reader, have or know of a career opportunity I can jump on, please drop a line to &lt;code&gt;hireme [at] paul [dot] glushak [dot] net&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Don’t be ashamed of needing help. You have a duty to fulfill just like a soldier on the wall of battle. So what if you are injured and can’t climb up without another soldier’s help?”&lt;br /&gt;
&lt;em&gt;– Marcus Aurelius&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:2-1"&gt;
&lt;p&gt;CSR – Central serous retinopathy. &lt;a href="https://en.wikipedia.org/wiki/Central_serious_chorioretinopathy"&gt;Wiki&lt;/a&gt;.&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><pubDate>Wed, 31 Dec 2025 00:00:00 -0000</pubDate></item><item><title>I Don’t Need an Office</title><link>https://0xff.nu/remote-work/</link><description>&lt;p&gt;&lt;img src="/./wfh-lol.png" /&gt;
We just don’t learn, do we? Not as employees, not as employers and not as people.&lt;/p&gt;
&lt;p&gt;As employees we’re not fighting for what we want, instead settling for whatever "perks" we’re so graciously given.&lt;/p&gt;
&lt;p&gt;As employers we’re not putting emphasis on what actually matters, instead flexing and peacocking our way into some abstract “Top X” list that shows to the whole world how big, shiny and important we are while inflating our ego like the US’ debt.&lt;/p&gt;
&lt;p&gt;As people we’re forgetting that not everyone operates or thinks the same way we do, opting instead to do our best to square everyone into the round template that we made up and decided is the right one while falsely proclaiming “I support diversity!” everywhere and as loudly as we possibly can.&lt;/p&gt;
&lt;p&gt;When the pandemic started and we were all shoved indoors and told to “stay inside, or else”, companies reluctantly allowed remote work. Guess what? Nothing collapsed. The world kept turning. Fragile egos of CEOs remained intact. Turns out working from home... worked. &lt;/p&gt;
&lt;p&gt;Fast forward three short years and the hedonic treadmill is back at full speed: one day a week in the office, then three, then “Remote? WFH? lol no.” Suddenly we’re trading hours of family time for a PlayStation, branded socks and a bowl of pretzels. We’re willing to practically donate our own time, money, and comfort to others. You work best when you’re not interrupted? Maybe you can focus and solve difficult problems only when you’re doing naked yoga in a pitch-black room? Welp, your boss swears they’re looking out for you, have your best interests in mind, and really think it’d be best for you to come in because “nothing beats a face-to-face conversation,” that “people need to physically see you,” and that “you collaborate better in one room together.” But has anyone ever asked YOU if that’s how you actually work best?&lt;/p&gt;
&lt;p&gt;Do you really fucking think we all have toddler-level object permanence? That if my coworkers don’t see me physically tumbling down the office hall I suddenly cease to exist? Do I suddenly communicate like a caveman just because my face shows up on a screen?&lt;br /&gt;
Is text or a video call somehow primitive compared to someone physically vibrating the air near your head?
Maybe it’s just your lack of trust, convinced we’re all drinking Pina coladas and being caught in the rain instead of working. Maybe it’s the absence of that little tingling you get while micro-managing and helicopter-parenting me over the shoulder.&lt;/p&gt;
&lt;p&gt;Please, tell me the actual, tangible, business need for me to be physically in the same building as you to do work that I already do just fine from home, a reason that is NOT some bullshit excuse dressed up as “socializing.” I’ll wait.&lt;/p&gt;
&lt;p&gt;It’s not about my work, it’s not about my output, it’s not about you seeing my messy hair shimmering in the fluorescent lights of the open-office halls, it sure as fuck is not about my comfort or me conserving precious mental resources and cognitive load while living with ADHD – it’s about your comfort. It’s about what makes YOU feel good, and all the rest be damned. &lt;/p&gt;
&lt;p&gt;But hey, even though I prefer remote work, let’s ignore the time wasted commuting for a second. I don’t live in the financial capital of Israel where most companies are located, and frankly I don’t want to, which apparently makes some employers picture me living in a barn with dial-up. So I still applied for hybrid roles. The responses I got? “Are you sure you can make the commute?” “We’re not near the rail line…” “We prefer people in the center.” So it’s lose-lose. Magical.&lt;/p&gt;
&lt;p&gt;And this is even though I live just over an hour away. What’s wasting three hours on commute between friends, amiright? And what about people even farther out from the golden kingdom? Sapir is two to four hours from TLV. Are we seriously pretending someone’s skills don’t count because they won’t sacrifice a quarter of their fucking day to traffic just to sit in your shiny, rented office?&lt;/p&gt;
&lt;p&gt;Snacks, a beer tap, a bowl of fruit or a fucking wi-fi connection (for us alleged dial-up peasants) are not worth missing dinner with my kids. Some of us prefer to pick them up from daycare and see them while they're still awake. Wild, I know&lt;/p&gt;
&lt;p&gt;I very much feel like “old man yelling at clouds”, knowing full well that this will not change – we’re too afraid to speak up, terrified to lose our employer-allocated spot under the sun.&lt;/p&gt;
&lt;p&gt;Remember this – 20 years from now, the only people who will remember that you worked late are your kids.&lt;/p&gt;
&lt;p&gt;Bottom line is – this fucking sucks. Here I am again, job-hunting in a market that feels stacked against me. Can I control what happens to my application after I click that "Submit" button? No, but what I can control is the framing I give this situation and what I personally do with it.
The speech by William McRaven comes to mind:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Every morning in basic SEAL training, my instructors, who at the time were all Vietnam veterans, would show up in my barracks room and the first thing they would inspect was your bed. If you did it right, the corners would be square, the covers pulled tight, the pillow centered just under the headboard and the extra blanket folded neatly at the foot of the rack — that’s Navy talk for bed.&lt;/p&gt;
&lt;p&gt;It was a simple task — mundane at best. But every morning we were required to make our bed to perfection. It seemed a little ridiculous at the time, particularly in light of the fact that were aspiring to be real warriors, tough battle-hardened SEALs, but the wisdom of this simple act has been proven to me many times over.&lt;/p&gt;
&lt;p&gt;If you make your bed every morning you will have accomplished the first task of the day. It will give you a small sense of pride, and it will encourage you to do another task and another and another. By the end of the day, that one task completed will have turned into many tasks completed. Making your bed will also reinforce the fact that little things in life matter. If you can’t do the little things right, you will never do the big things right.&lt;/p&gt;
&lt;p&gt;And, if by chance you have a miserable day, you will come home to a bed that is made — that you made — and a made bed gives you encouragement that tomorrow will be better.&lt;/p&gt;
&lt;p&gt;If you want to change the world, start off by making your bed.&lt;/p&gt;
&lt;p&gt;– &lt;em&gt;Admiral William H. McRaven&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So here I am, making my bed, completing the tasks I &lt;em&gt;can&lt;/em&gt; complete in an otherwise unknown and random environment: raising my five-year-old and newborn son with my wife, planning, sketching and learning Swift to develop an iOS app, creating and improving personal tools in Python and Crystal, all while trying to apply to jobs, both the good ones and the ones that expect me to sacrifice myself and my family for an office chair.&lt;/p&gt;
&lt;p&gt;We’re all people. We should all be able to choose what works for us, and we should accept what works for others.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I'm well aware there are companies that are different. I'm simply stating the default.&lt;/li&gt;
&lt;li&gt;I'm also well aware there are tasks or roles that require you to be physically present.&lt;/li&gt;
&lt;li&gt;This 'rant' is not about either of those.&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Fri, 05 Dec 2025 00:00:00 -0000</pubDate></item><item><title>Automating ADHD</title><link>https://0xff.nu/automating-adhd/</link><description>&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;p&gt;This article will be constantly updated with new solutions and improvements to existing solutions that I implement for myself.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;The automations below require some hardware (sensors, zigbee radio) and software (Home Assistant), but can probably achieved with other combinations.
Adapt the logic to your needs and constraints!&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;As I'm sure I wrote before – &lt;a href="/productivity"&gt;I have ADHD&lt;/a&gt;, which comes with a unique set of benefits, but also a fucking mountain of challenges. It is also the catalyst and driving force behind a large chunk of my personal projects.&lt;/p&gt;
&lt;p&gt;And so, as part of my never-ending pursuit for improving and streamlining as much of my daily life as possible, I decided to try and tackle some of those annoying tasks that most of us (yes, even people that don't have "a little bit of ADHD") just tend to forget to do.&lt;/p&gt;
&lt;div class="toc"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#automatic"&gt;Automatic&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#reminding-me-to-cleaning-the-cats-litter-box"&gt;Reminding me to cleaning the cats' litter-box&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#reminding-me-to-take-my-meds"&gt;Reminding me to take my meds&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#hardware-requirements"&gt;Hardware Requirements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#the-setup"&gt;The Setup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#interaction-based"&gt;Interaction Based&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#reminding-me-to-buy-cat-food-and-litter"&gt;Reminding me to buy cat food and litter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#important-shopping-list"&gt;Important Shopping List&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id="automatic"&gt;Automatic&lt;a class="headerlink" href="#automatic" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="reminding-me-to-cleaning-the-cats-litter-box"&gt;Reminding me to cleaning the cats' litter-box&lt;a class="headerlink" href="#reminding-me-to-cleaning-the-cats-litter-box" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;This can, and probably should, be further improved to complete existing tasks for example, instead of having to complete them manually.&lt;/p&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hardware&lt;/strong&gt; – Zigbee door/window sensor (magnetic reed switch or hall effect)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Software&lt;/strong&gt; – Todo app with an API integration in HomeAssistant&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The principle of this automation, which actually has two parts, is both create a reminder that is based on completion date and nag me in case I forgot to remove the bio-hazard waste.&lt;/p&gt;
&lt;p&gt;The magic is achieved by placing the magnetic switch on the drawer of the litter-box, which you ideally will only open when performing maintenance on the feline waste container.&lt;/p&gt;
&lt;h3 id="reminding-me-to-take-my-meds"&gt;Reminding me to take my meds&lt;a class="headerlink" href="#reminding-me-to-take-my-meds" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Due to the configuration oddities of the sensor, fine-tuning this automation may be more difficult than necessary. But with some extra logic you'll be able to do it!&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I often forget to take my meds in the morning, especially with how hectic some mornings may be, and even though my phone gently nudges me to take the meds at 8:35AM (and then &lt;del&gt;punches me in the ribs&lt;/del&gt; yells much louder at 9:15AM), I will still forget to do so.&lt;/p&gt;
&lt;p&gt;So I came up with a solution through HomeAssistant to keep annoying me until I take my meds.&lt;/p&gt;
&lt;h4 id="hardware-requirements"&gt;Hardware Requirements&lt;a class="headerlink" href="#hardware-requirements" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Vibration sensor that can report &lt;a href="https://www.zigbee2mqtt.io/supported-devices/#e=x_axis"&gt;XYZ&lt;/a&gt; or &lt;a href="https://www.zigbee2mqtt.io/supported-devices/#e=tilt"&gt;tilt&lt;/a&gt; and can comfortably fit in/on your jar&lt;/li&gt;
&lt;li&gt;A jar or a box that can safely store medicine&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="the-setup"&gt;The Setup&lt;a class="headerlink" href="#the-setup" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Create a &lt;strong&gt;Input Boolean&lt;/strong&gt; helper in &lt;a href="https://my.home-assistant.io/redirect/helpers/"&gt;helpers&lt;/a&gt;. I called mine &lt;code&gt;Paul Meds Taken&lt;/code&gt; and gave it the &lt;code&gt;mdi:pill&lt;/code&gt; icon&lt;/li&gt;
&lt;li&gt;Create a reset &lt;strong&gt;Automation&lt;/strong&gt; in &lt;a href="https://my.home-assistant.io/redirect/automations/"&gt;automations&lt;/a&gt;. The gist is to reset the boolean at midnight&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class="language-YAML"&gt;alias: Reset Meds Taken Status
description: &amp;gt;-
  Automatically reset the medication status to 'not taken' at midnight if it was
  marked as taken.
triggers:
  - trigger: time
    at: &amp;quot;00:00:00&amp;quot;
conditions: []
actions:
  - action: input_boolean.turn_off
    metadata: {}
    data: {}
    target:
      entity_id: input_boolean.paul_meds_taken
mode: single
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;Create a reminder &lt;strong&gt;Automation&lt;/strong&gt; which will constantly nag you to take your meds, until the boolean you created earlier is set as &lt;code&gt;true&lt;/code&gt;.&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;For my automation, I also included the phone location, as if I'm not home (which is where the drugs are) there's no reason to constantly nag me.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class="language-YAML"&gt;alias: &amp;quot;Reminder to Take Meds&amp;quot;
description: Automatically reminds Paul to take his medications every hour if not done by 12 PM.
triggers:
  - trigger: time_pattern
    hours: /1 #Reminder every hour
conditions:
  - condition: and
    conditions:
      - condition: time
        after: &amp;quot;08:00:00&amp;quot;
        before: &amp;quot;12:00:00&amp;quot;
      - condition: state
        entity_id: input_boolean.paul_meds_taken
        state:
          - &amp;quot;off&amp;quot;
      - condition: zone
        entity_id: person.paul
        zone: zone.home_city
actions:
  - action: notify.mobile_app_phoney
    metadata: {}
    data:
      message: 💊 TAKE YOUR MEDS
      title: 💊 TAKE YOUR MEDS
mode: single   
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;Create an &lt;strong&gt;Automation&lt;/strong&gt; to indicate you've taken your government-issued brain medication.&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Note the zone check in this automation. It's there to prevent turning the automation off by mistake in case my wife decides to pick up the happiness jar.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class="language-YAML"&gt;alias: Paul – Cancel Medication Reminder
description: &amp;gt;-
  This automation activates when the medbox lid is tilted and sets
  the helper as true meaning meds taken.
triggers:
  - trigger: state
    entity_id:
      - binary_sensor.medbox_vibration_sensor_tilt
    from:
      - &amp;quot;off&amp;quot;
    to:
      - &amp;quot;on&amp;quot;
    for:
      hours: 0
      minutes: 0
      seconds: 3
conditions:
  - condition: and
    conditions:
      - condition: time
        after: &amp;quot;07:00:00&amp;quot;
      - condition: state
        entity_id: input_boolean.paul_meds_taken
        state:
          - &amp;quot;off&amp;quot;
      - condition: zone
        entity_id: person.paul
        zone: zone.home_city
actions:
  - action: input_boolean.turn_on
    metadata: {}
    data: {}
    target:
      entity_id: input_boolean.paul_meds_taken
  - action: notify.ntfy_home
    metadata: {}
    data:
      title: MedBox
      message: Paul took his meds
mode: single
&lt;/code&gt;&lt;/pre&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Wife's Version&lt;/p&gt;
&lt;p&gt;I ended up being able to convince my wife to allow me to create a similar automation for her, as she also seldom forgets to partake in the medicinal journey, albeit with her own pills.
She however, did not want to put her medication in a small jar with a vibration sensor glued to it, so I proposed a different solution for her. The principle is the same to the one I use, but the activation is different.
1. Wife forgets to take her medication
2. A notification is being broadcast through &lt;strong&gt;NTFY&lt;/strong&gt; as well as the living room smart speaker
3. Wife scans an &lt;strong&gt;NFC Tag&lt;/strong&gt; which runs a &lt;strong&gt;iOS Shortcuts Automation&lt;/strong&gt; 
4. The automation pens the &lt;strong&gt;Health&lt;/strong&gt; app on the Medication view and executes a &lt;strong&gt;HomeAssistant Automation&lt;/strong&gt; which sends a &lt;strong&gt;NTFY&lt;/strong&gt; notification and sets the &lt;strong&gt;Input Boolean&lt;/strong&gt; to true&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id="interaction-based"&gt;Interaction Based&lt;a class="headerlink" href="#interaction-based" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="reminding-me-to-buy-cat-food-and-litter"&gt;Reminding me to buy cat food and litter&lt;a class="headerlink" href="#reminding-me-to-buy-cat-food-and-litter" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;h3 id="important-shopping-list"&gt;Important Shopping List&lt;a class="headerlink" href="#important-shopping-list" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;</description><pubDate>Wed, 26 Nov 2025 00:00:00 -0000</pubDate></item><item><title>New Beginnings, 2025 edition</title><link>https://0xff.nu/news-2025/</link><description>&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;TL;DR&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Got laid off because of █u████it█ ██d█ up ██a██n█.&lt;/li&gt;
&lt;li&gt;Went on a trip to Italy with pregnant wife and the kid – &lt;code&gt;2091.7km&lt;/code&gt; in an EV.&lt;/li&gt;
&lt;li&gt;I'm now the father of two boys.&lt;/li&gt;
&lt;li&gt;My eyes are betraying me.&lt;/li&gt;
&lt;li&gt;Found a job as a contractor at &lt;a href="https://usetrmnl.com"&gt;TRMNL&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Got laid off (again), as the expectations were not aligned (I'm doing more dev work than support). We're still friends.&lt;/li&gt;
&lt;li&gt;Had &amp;gt; 40 project notes created this year. Fucking ADHD.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img alt="Lol, 2025" src="/nov-2025-updates.png" /&gt;&lt;/p&gt;
&lt;p&gt;I kinda disappeared for a while it seems, but only because a lot of things were happening all at once, so I chose to shift and adjust my focus to be able to deal with each thing separately.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We move forward&lt;br /&gt;
'Cause we can't go back&lt;/p&gt;
&lt;p&gt;– &lt;em&gt;The Midnight&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="previous-previous-previous-job"&gt;&lt;del&gt;Previous&lt;/del&gt; Previous, Previous Job&lt;a class="headerlink" href="#previous-previous-previous-job" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Unfortunately, my time as &lt;em&gt;R&amp;amp;D Solutions Manager&lt;/em&gt; at &lt;a href="https://forter.com"&gt;Forter&lt;/a&gt; came to an end. I've learned a lot, gained a lot, created a lot and met some amazing people. I could've done more, alas it's not possible. Not going to go into it.&lt;/p&gt;
&lt;h2 id="new-previous-job"&gt;&lt;del&gt;New&lt;/del&gt; Previous Job&lt;a class="headerlink" href="#new-previous-job" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Bought myself a &lt;a href="https://shop.usetrmnl.com/products/trmnl"&gt;TRMNL OG&lt;/a&gt; earlier this year to consolidate calendars and tasks in a nice family dashboard. Figured it could be great to work in a company whose product you love, and chose to use.&lt;/p&gt;
&lt;p&gt;I got lucky, and joined as a contractor (had to learn about registering and working as a sole proprietor in the process) at TRMNL as a Support Engineer. Things were said, hands were shook, and right after our family trip I got to work. I feel like I contributed and learned quite a lot, but there was some sort of miscommunication and/or misalignment and me doing more development than support was not what the company was looking for.&lt;/p&gt;
&lt;p&gt;You know what, yeah I didn't answer a lot of customer tickets, but here is what I did accomplish &lt;em&gt;except&lt;/em&gt; tickets:
- I did all of the things below while learning Ruby, Rails, Active Admin and TRMNL's own code.
- Introduced categorization into the ticketing system (Intercom).
- Added a few new custom attributes to Intercom via &lt;a href="https://github.com/intercom/intercom-rails"&gt;intercom-rails&lt;/a&gt;.
- Identified the need and added QR support to TRMNL's Liquid Gem, instead of customers using JS libs.
- Added battery voltage and percentage to the low battery automatic email that is being sent out to customers.
- Added battery voltage and percentage based coloring to the battery bar in TRMNL's Admin Dashboard (&lt;code&gt;activeadmin&lt;/code&gt;).
- Added inactive device styling to TRMNL's Admin Dashboard.
- Found and suggested the solution to &lt;a href="https://discord.com/channels/1281055965508141100/1439400817638637770"&gt;not being able to use CTRL+A&lt;/a&gt; in &lt;code&gt;select&lt;/code&gt; fields that have &lt;code&gt;multiple&lt;/code&gt; enabled.
- Identified and reported a vulnerability in TRMNL plugins where a malicious actor could:
    - Replace the code in a third party JS thus breaking or hijacking plugins and what they display on end users' screens
    - Steal tokens/passwords through the exposed &lt;code&gt;{{ trmnl }}&lt;/code&gt; variable which can include &lt;code&gt;password&lt;/code&gt; custom fields
- Added a helpful tooltip to use keyboard keys for multi selection:&lt;img src="/trmnl-keyboard-hint.png" /&gt;
- Improved the structure of &lt;a href="https://help.usetrmnl.com/en/articles/10513740-custom-plugin-form-builder"&gt;Custom plugin form builder&lt;/a&gt; article.
- Had an extensive meeting with a team-mate about HomeAssistant where I demonstrated my own dashboard, explained the intricacies and importance of certain aspects and discussed ways of connecting the two.
- Wrote a doc with ideas on how to improve the support function in TRMNL via moderation improvements, support streamlining and consolidation and creating custom CLI tools to aid in workflows.&lt;/p&gt;
&lt;p&gt;Does it suck? Yes, very much so. But you know what? Juggling a child on the spectrum, a pregnant wife and then a newborn, house chores and learning an entirely new fucking codebase in a language I do not code in – I'm proud of what I accomplished, and I don't see this as a failure.&lt;/p&gt;
&lt;p&gt;We're still friends, and I've got a lot of TRMNL plugins in my backlog that I'd like to finish.&lt;/p&gt;
&lt;h2 id="italy"&gt;Italy&lt;a class="headerlink" href="#italy" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Once I was laid off from Forter, I made a decision that we absolutely have to go for a family trip to recuperate, especially before my wife gives birth.&lt;/p&gt;
&lt;p&gt;We made a decision to rent an EV for this trip as we figured it will be a good sampler of living with an EV, considering we're planning on replacing our car. Sure, we can't buy the car we rented (Audi A6 e-tron Quattro!), but we got a glimpse of how good it can be, so we have a good point of comparison.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[!INFO] TL;DR
Milan, Italy -&amp;gt; Simplon Pass -&amp;gt; Geneva, Switzerland -&amp;gt; Great St. Bernard Pass -&amp;gt; Valle di Aosta, Italy -&amp;gt; Sanremo, Italy -&amp;gt; Monaco -&amp;gt; Portofino -&amp;gt; Modena -&amp;gt; Lago di Garda -&amp;gt; Milan&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="csr"&gt;CSR&lt;a class="headerlink" href="#csr" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Central Serous Retinopathy&lt;/strong&gt; is a new term I had to learn about. The hard way. At some point during September I started noticing a degradation in my vision, specifically my right eye – I was finding it difficult to focus on things, primarily on text on a screen (which, as you might guess, is also part of my work). &lt;/p&gt;
&lt;p&gt;So I've visited an optometrist thinking it might be something simple – maybe I looked at a light that was too bright or, you know, being over 30 – maybe I burped too hard.&lt;/p&gt;
&lt;p&gt;Turns out I've got a fucking liquid bubble, which according to two of the consequent doctors that I saw might be caused by stress. Right. Well, fuck.&lt;/p&gt;</description><pubDate>Fri, 26 Sep 2025 00:00:00 -0000</pubDate></item><item><title>mkcv</title><link>https://0xff.nu/mkcv/</link><description>&lt;h2 id="what-is-this"&gt;What is this?&lt;a class="headerlink" href="#what-is-this" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;mkcv&lt;/code&gt; is a small and quick project designed to generate a resume from a YAML definition.&lt;/p&gt;
&lt;h2 id="why"&gt;Why?&lt;a class="headerlink" href="#why" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Seeing as quite a lot of people are being laid off recently, and in an effort to keep my own resume up to date, I wanted to try and minimize the effort it takes to keep multiple outputs up to date.&lt;/p&gt;
&lt;p&gt;The idea is to generate an HTML file that can be used for a webpage, and a PDF that can be either downloaded or sent out.&lt;/p&gt;
&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;p&gt;The PDF part is not working well at the moment, as I'm still figuring out how to get &lt;code&gt;weasyprint&lt;/code&gt; to behave.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id="installation"&gt;Installation&lt;a class="headerlink" href="#installation" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="local"&gt;Local&lt;a class="headerlink" href="#local" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;mkcv&lt;/code&gt; can be installed as a tool locally with &lt;code&gt;uv&lt;/code&gt; by running &lt;code&gt;uv tool install git+https://git.sr.ht/~hxii/mkcv&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="github-workflow"&gt;GitHub Workflow&lt;a class="headerlink" href="#github-workflow" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can use &lt;code&gt;mkcv&lt;/code&gt; to automatically keep your GitHub Pages resume up to date with GitHub Workflows.&lt;/p&gt;
&lt;p&gt;Here's an example workflow:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-YAML"&gt;name: Generate and Deploy CV

on:
  push:
    branches: [main]
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout data and template from GitHub
        uses: actions/checkout@v4
      - name: Install the latest version of uv
        uses: astral-sh/setup-uv@v6
        with:
          version: &amp;quot;latest&amp;quot;
      - name: Install mkcv dependencies with uv tool install
        run: |
          uv tool install git+https://git.sr.ht/~hxii/mkcv
      - name: Generate CV HTML
        run: uvx mkcv -vvv -o ./_site
      - name: Rename index
        run: mv ./_site/cv.html ./_site/index.html
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3

  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="usage"&gt;Usage&lt;a class="headerlink" href="#usage" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;All paths are relative to where the command is being run. &lt;code&gt;mkcv&lt;/code&gt; will by default look for &lt;code&gt;./data/cv.yaml&lt;/code&gt; and &lt;code&gt;./data/template/cv.jinja&lt;/code&gt; files for your resume and template respectively.&lt;/p&gt;
&lt;p&gt;These can be changed with the &lt;code&gt;-f ~/my_cv.yaml&lt;/code&gt; and &lt;code&gt;-t ~/my_cv_template/&lt;/code&gt; flags.&lt;/p&gt;
&lt;p&gt;The output by default will go to &lt;code&gt;./output&lt;/code&gt; which can also be changed with the &lt;code&gt;-o ~/my_cv_html/&lt;/code&gt; flag.&lt;/p&gt;
&lt;h3 id="cv-example"&gt;CV Example&lt;a class="headerlink" href="#cv-example" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Your resume should be defined as a YAML file, which to me is quite humanly readable:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-YAML"&gt;personal_information: # Personal info
  full_name: John Doe
  email: john@doe.net
  phone: &amp;quot;555-1234&amp;quot;
  title: CEO
  website: https://sample.com
companies: # A list of companies
  - name: MegaCorp
    url: https://megacorp.com
  - name: SmallCorp
experience: # A list of positions
  - title: CEO
    company: MegaCorp
    start_date: &amp;quot;2020-01-01&amp;quot;
    description: |
      Just the CEO. I compulsively, extensively observe things.
    icon: pikachu
  - title: Not CEO
    company: SmallCorp
    start_date: &amp;quot;1990-01-01&amp;quot;
    end_date: &amp;quot;2020-01-01&amp;quot;
    description: &amp;quot;I wasn't the CEO, if that's what you're asking!&amp;quot;
skills: # A list of skills that can be tied to a company
  - title: Management
    company: megacorp
  - title: C++
  - title: Coffee making
links: # A list of links, e.g. github, your website
  - url: https://sample.com
    title: Personal Website
    class: link--highlight
  - url: https://google.com
    title: My least favorite search engine
    style: |
      font-weight: bold
  - title: Where I look for praises
    url: https://www.linkedin.com/
    icon: linkedin
projects: # A list of projects that can be tied to company
  - title: Boku
    url: https://sample.com
    description: I designed my website!
    start_date: &amp;quot;2024-01-01&amp;quot;
    icon: briefcase
showcase: # Basically the same as projects, but anything you want to showcase
  - title: Sample Project
    url: https://example.com
    icon: submarine
extra: # Any extra sections
  interests:
    title: Extra Section
    content: Extra section you can use in your template
&lt;/code&gt;&lt;/pre&gt;</description><pubDate>Sun, 27 Jul 2025 00:00:00 -0000</pubDate></item><item><title>iOS Shortcuts</title><link>https://0xff.nu/ios-shortcuts/</link><description>&lt;div class="toc"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#why-shortcuts"&gt;Why Shortcuts?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#new-things"&gt;New Things&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#what-have-i-created"&gt;What have I created?&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#uber-shortcut"&gt;Uber Shortcut&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#action-button"&gt;Action Button&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#radio-picker"&gt;Radio Picker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#daily-quick-notes"&gt;Daily Quick Notes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;When we're not spending our evenings behind a heavy metal door, one of the things I find myself fucking around with is iOS' Shortcuts app.
Yes yes, one of the reasons I switched to the iPhone was so that I'll stop screwing with my mobile device, but hear me out - Shortcuts are magical.&lt;/p&gt;
&lt;p&gt;With iOS 26 it seems like Apple has fixed some gripes I've had with Shortcuts (e.g. not being able to return to your app/screen of origin after running a shortcut), and I've decided to use the opportunity to make a post where I can also share some of the shortcuts I use almost daily.&lt;/p&gt;
&lt;h2 id="why-shortcuts"&gt;Why Shortcuts?&lt;a class="headerlink" href="#why-shortcuts" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Ever since I've test driven the iPhone 11 (i.e. just before I switched from Android) and checked out the Shortcuts app, then on iOS 17, I understood the power and comfort it brought to the average Apple user.&lt;/p&gt;
&lt;p&gt;While Shortcuts could be easy as pie (i.e. vanilla), or complex as fuck (via Actions for Obsidian, Toolbox Pro, Actions and so on), in my personal experience I've found that unlike the alternatives on the other side of the fence (Automate, Tasker etc.), they don't necessarily require you to recite the Necronomicon or partake in IKEA summoning rituals to get them to do what you need them to do.&lt;/p&gt;
&lt;p&gt;So I've decided to create some useful tools for myself, which became even more useful once I got an iPhone 15 Pro which has that fancy shortcut button.&lt;/p&gt;
&lt;h2 id="new-things"&gt;New Things&lt;a class="headerlink" href="#new-things" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I am currently on iOS 26 Developer Beta, and looks like some of my gripes with Shortcuts have been resolved:
1. Apple have added a great "Get Current App" action which allows you to return to the app you were in prior to running the shortcut.&lt;/p&gt;
&lt;h2 id="what-have-i-created"&gt;What have I created?&lt;a class="headerlink" href="#what-have-i-created" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="uber-shortcut"&gt;Uber Shortcut&lt;a class="headerlink" href="#uber-shortcut" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;p&gt;This shortcut requires an additional app - &lt;a href="https://apps.apple.com/us/app/menu-box/id6463440793"&gt;Menu Box&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Menu Box is a QoL app that allows you to create nicer looking menus, and is not a must. You can adapt the shortcut to use "Choose from List" instead.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;iCloud Link: &lt;a href="https://www.icloud.com/shortcuts/92af31e498984175abb536b38b2469c2"&gt;https://www.icloud.com/shortcuts/92af31e498984175abb536b38b2469c2&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Direct File: N/A&lt;/p&gt;
&lt;p&gt;Setup: An import question will ask for a folder where your shortcuts are located.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;This shortcut allows me to launch a bunch of shortcuts with the shortcut button by showing me a menu with all the shortcuts from a specific folder.&lt;/p&gt;
&lt;h3 id="action-button"&gt;Action Button&lt;a class="headerlink" href="#action-button" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;p&gt;This shortcut requires an additional app - &lt;a href="https://apps.apple.com/us/app/actions/id1586435171"&gt;Actions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Actions adds a shit ton of useful functionality to Shortcuts in general, and specifically the "Is Device Orientation" action that this shortcut uses.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;iCloud Link: &lt;a href="https://www.icloud.com/shortcuts/c287352667b34193bb94399f3e1a53fe"&gt;https://www.icloud.com/shortcuts/c287352667b34193bb94399f3e1a53fe&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Direct File: N/A&lt;/p&gt;
&lt;p&gt;Setup:
1. You can do something else instead of opening the camera if the device is horizontal.
2. Make sure to choose "Uber Shortcut" as the last action&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I use the "Action Button" shortcut in tandem with Uber Shortcut to allow me to do two more actions. Think of this as a very, VERY simple context awareness.
1. If the device is locked, toggle Silent Mode.
2. If the device is horizontal, open the Camera.
3. Otherwise, run Uber Shortcut.&lt;/p&gt;
&lt;h3 id="radio-picker"&gt;Radio Picker&lt;a class="headerlink" href="#radio-picker" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;iCloud Link: &lt;a href="https://www.icloud.com/shortcuts/5a6bf701e653425e9559810b5df1801a"&gt;https://www.icloud.com/shortcuts/5a6bf701e653425e9559810b5df1801a&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Direct File: N/A&lt;/p&gt;
&lt;p&gt;Setup: Add your own radio stations to the dictionary where &lt;code&gt;key -&amp;gt; value&lt;/code&gt; is &lt;code&gt;station name -&amp;gt; station URL&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;A quick online radio picker, very useful when driving.&lt;/p&gt;
&lt;h3 id="daily-quick-notes"&gt;Daily Quick Notes&lt;a class="headerlink" href="#daily-quick-notes" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;iCloud Link: &lt;a href="https://www.icloud.com/shortcuts/e395214ecf8b4c1fa58facf3eda9a0fb"&gt;https://www.icloud.com/shortcuts/e395214ecf8b4c1fa58facf3eda9a0fb&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Direct File: N/A&lt;/p&gt;
&lt;p&gt;Setup: N/A&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;This shortcut will ask for your note, and append it as &lt;code&gt;* &amp;lt;time in H:MM:SS format&amp;gt; &amp;lt;your note&amp;gt;&lt;/code&gt; to a a daily note.
If the daily note doesn't exist, it will create it as &lt;code&gt;YYYY-MM-DD&lt;/code&gt; and tag it as &lt;code&gt;#daily-note&lt;/code&gt;.&lt;/p&gt;</description><pubDate>Sat, 14 Jun 2025 00:00:00 -0000</pubDate></item><item><title>Dengonban</title><link>https://0xff.nu/dengonban/</link><description>&lt;p&gt;&lt;img alt="Dengonban Header Image" src="/Dengonban.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://sr.ht/~hxii/dengonban/"&gt;Source&lt;/a&gt; | &lt;a href="https://todo.sr.ht/~hxii/dengonban"&gt;Issues and Feature Requests&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="what-is-this"&gt;What is this?&lt;a class="headerlink" href="#what-is-this" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Dengonban (伝言板, "Message Board" in Japanese) is a &lt;a href="https://usetrmnl.com"&gt;TRMNL&lt;/a&gt; plugin to provide a notice board functionality to the device.&lt;/p&gt;
&lt;h2 id="why"&gt;Why?&lt;a class="headerlink" href="#why" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Having received my TRMNL device, I figured a nice addition would be to create a plugin that will allow me and my wife to leave async messages for each other.
Think of this like a announcement or a reminder.
And while you can definitely just send webhooks and let TRMNL do the rest with the data, I figured having the ability to manage these messages could also be nice.
So I've decided to create my first docker-ized app.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Dengonban Dashboard" src="/dengonban-dashboard.png" /&gt;&lt;/p&gt;
&lt;h2 id="installation"&gt;Installation&lt;a class="headerlink" href="#installation" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="local-build"&gt;Local Build&lt;a class="headerlink" href="#local-build" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The easiest way to get this to work is as follows:
1. Clone the repository: &lt;code&gt;git clone https://git.sr.ht/~hxii/dengonban&lt;/code&gt;
2. &lt;code&gt;cd&lt;/code&gt; into the cloned repository
3. Create a token for TRMNL: &lt;code&gt;./create-token.py -t&lt;/code&gt;
4. Create a token for yourself: &lt;code&gt;./create-token -u &amp;lt;your-name&amp;gt;&lt;/code&gt;
5. Build the image: &lt;code&gt;make build&lt;/code&gt;
6. Run the image: &lt;code&gt;DASHBOARD_ENABLED=1 make run&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="docker-compose"&gt;Docker Compose&lt;a class="headerlink" href="#docker-compose" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Clone the repository: &lt;code&gt;git clone https://git.sr.ht/~hxii/dengonban&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd&lt;/code&gt; into the cloned repository&lt;/li&gt;
&lt;li&gt;Create a token for TRMNL: &lt;code&gt;./create-token.py -t&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create a token for yourself: &lt;code&gt;./create-token -u &amp;lt;your-name&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Edit &lt;code&gt;docker-compose.yml&lt;/code&gt; to include the &lt;code&gt;DASHBOARD_ENABLED&lt;/code&gt; environment variable if you want the dashboard enabled&lt;/li&gt;
&lt;li&gt;Run compose: &lt;code&gt;docker-compose up&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="portainer"&gt;Portainer&lt;a class="headerlink" href="#portainer" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Clone the repository: &lt;code&gt;git clone https://git.sr.ht/~hxii/dengonban&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;cd` into the cloned repository&lt;/li&gt;
&lt;li&gt;Create a token for TRMNL: &lt;code&gt;./create-token.py -t&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create a token for yourself: &lt;code&gt;./create-token -u &amp;lt;your-name&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create a new container in Portainer&lt;/li&gt;
&lt;li&gt;Set "Image" to &lt;code&gt;hxii0/dengonban:latest&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Map the container's &lt;code&gt;8000&lt;/code&gt; port to whichever port of your host that you want&lt;/li&gt;
&lt;li&gt;Create a volume mount for the container's &lt;code&gt;/app/data&lt;/code&gt; directory pointing to wherever you cloned the repository&lt;/li&gt;
&lt;li&gt;Add the &lt;code&gt;DASHBOARD_ENABLED&lt;/code&gt; environment variable with the value &lt;code&gt;1&lt;/code&gt; to enable dashboard&lt;/li&gt;
&lt;li&gt;Run it&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="features"&gt;Features&lt;a class="headerlink" href="#features" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;FastAPI CRUD endpoints for messages&lt;/li&gt;
&lt;li&gt;Simple dashboard&lt;/li&gt;
&lt;li&gt;Different message types (configured in &lt;code&gt;data/message-types.json&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Message expiration time&lt;/li&gt;
&lt;li&gt;Multiple people&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Sun, 01 Jun 2025 00:00:00 -0000</pubDate></item><item><title>Update, May 2025</title><link>https://0xff.nu/updates-may-2025/</link><description>&lt;p&gt;The past three months felt very hectic for me, and at times it felt as if I was losing any sliver of control over things that I, personally, wanted to accomplish. Driven by work, fatherhood and sense of impending &lt;del&gt;doom&lt;/del&gt; move (which, thank fuck, is now behind us... almost. Fucking never-ending boxes!), the mental capacity that I could devote towards self-expression and creation just.. wasn't there. Yet, as we do, I persevered and managed to get some important fixes out for &lt;a class="wikilink" href="/Hajime"&gt;Hajime&lt;/a&gt; as well as the star of this post - &lt;a class="wikilink" href="/Boku."&gt;Boku&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While writing this update I have realized that I initially started working on &lt;a class="wikilink" href="/blog/boku"&gt;Boku&lt;/a&gt; on and off &lt;em&gt;just&lt;/em&gt; over a year ago on May 14th 2024. If I was a professional developer, or at least better at managing my own time, I'm fairly sure that the result of a (gross) year worth of work would've been better. But..
&lt;img src="/may-2025-not-great.png" /&gt;&lt;/p&gt;
&lt;h2 id="boku"&gt;Boku&lt;a class="headerlink" href="#boku" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The goal was, and remains to create a tool that is &lt;strong&gt;personal&lt;/strong&gt; and is a comfortable stop-gap solution to, perhaps, a very small problem, not necessarily something that is feature complete and that can provide a worthy alternative to the hundreds of better tools out there, and so, even though &lt;code&gt;boku&lt;/code&gt; can't do everything, I am proud of what I managed to accomplish, because being able to do&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tasks:
 get_os:
  run: uname -s
  save_output: os
 ensure_brew:
  run: command -v brew
 install_brewfile:
  depends_on: ensure_brew
  run: brew bundle install --file ${os}Brewfile
  on_failure: echo &amp;quot;Brew has to be installed!&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(for example) to install an OS dependent &lt;code&gt;Brewfile&lt;/code&gt; from my dotfiles feels... great.&lt;/p&gt;
&lt;p&gt;Boku version 0.2.3 is available on &lt;a href="https://git.sr.ht/~hxii/boku/refs/0.2.3"&gt;SourceHut&lt;/a&gt;.&lt;/p&gt;
&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I haven't fully figured out how to work with artifacts and releases on SourceHut.&lt;/li&gt;
&lt;li&gt;The documentation is not as full as it should be, but I'm working on it.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id="trmnl"&gt;TRMNL&lt;a class="headerlink" href="#trmnl" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As I'm writing this update, my &lt;a href="https://usetrmnl.com/"&gt;TRMNL&lt;/a&gt; is just around the corner, waiting to be delivered. Once I have it, I believe the quality and quantity of plugins I make for it will increase.
That being said, while waiting for my device to arrive I wrote a &lt;a href="https://usetrmnl.com/recipes/34578/install"&gt;Today's Mealie Plan&lt;/a&gt; and &lt;a href="https://usetrmnl.com/recipes/33478/install"&gt;Miniflux Feed&lt;/a&gt; plugins.&lt;/p&gt;
&lt;p&gt;&lt;a class="wikilink" href="/Dengonban"&gt;Dengonban&lt;/a&gt; is still not ready though.&lt;/p&gt;
&lt;p&gt;&lt;img src="/dengonban_preview.png" /&gt;&lt;/p&gt;
&lt;h2 id="life"&gt;Life&lt;a class="headerlink" href="#life" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;We're having another child on the way! This is sure going to be interesting.&lt;/li&gt;
&lt;li&gt;After 7 years of staying in the same apartment, we've finally decided it's time to move to a bigger place. This was physically demanding, even though we've paid a moving company to move 80% of the stuff.
  But you know what they say about the 80-20 rule, right?&lt;/li&gt;
&lt;li&gt;Since we've moved, the new place (1 month in) still looks like a warzone as we've yet to figure out where everything needs to go.&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Wed, 21 May 2025 00:00:00 -0000</pubDate></item><item><title>Hajime + Obsidian = 🤯</title><link>https://0xff.nu/hajime-plus-obsidian/</link><description>&lt;p&gt;Having recently made some adjustments to &lt;a class="wikilink" href="/hajime"&gt;Hajime&lt;/a&gt; to make it possible to author posts via Obsidian,
all I have to do now is write something somewhat coherent in Obsidian and run a command in 
Obsidian (or throw some gang signs that resemble a hotkey, if that's your jam).&lt;/p&gt;
&lt;p&gt;Here's a short guide on how I set it up.&lt;/p&gt;
&lt;h2 id="requirements"&gt;Requirements&lt;a class="headerlink" href="#requirements" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://git.sr.ht/~hxii/hajime/refs/0.5.7"&gt;Hajime 0.5.7 and above&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Obsidian.&lt;/li&gt;
&lt;li&gt;&lt;a href="obsidian://show-plugin?id=obsidian-shellcommands"&gt;Shell commands plugin for Obsidian&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;Optional: Sourcehut/Github build workflow.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-how"&gt;The How&lt;a class="headerlink" href="#the-how" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="hajime"&gt;Hajime&lt;a class="headerlink" href="#hajime" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The first step is to configure the Hajime repository and make some changes.
I moved all my posts from &lt;code&gt;~/dev/blog/source&lt;/code&gt; to a dedicated folder in my vault: &lt;code&gt;~/Vaults/brain/blog&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then, I enabled "copy mode" by setting &lt;code&gt;copy_entries_to_local_source&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; and changed 
the value of &lt;code&gt;source_folder&lt;/code&gt; to the new directory in my Obsidian vault: &lt;code&gt;"~/Vaults/brain/blog"&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;My &lt;code&gt;hajime.toml&lt;/code&gt; file looks as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-toml"&gt;[meta]
version = &amp;quot;0.5.6&amp;quot;
folder_hierarchy = true
sync_commit = true
sync_push = true
disallow_publish_override = false
copy_entries_to_local_source = true

[folders]
source_folder = &amp;quot;~/Vaults/brain/blog&amp;quot;
output_folder = &amp;quot;html&amp;quot;
template_folder = &amp;quot;template&amp;quot;

[include]

[exclude]
tags = [&amp;quot;hide&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="obsidian"&gt;Obsidian&lt;a class="headerlink" href="#obsidian" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To avoid reaching for the terminal every time I want to update my blog the initial plan was to write a simple plugin
(I still might do that... at some point) to handle the &lt;code&gt;sync&lt;/code&gt; process of Hajime.&lt;/p&gt;
&lt;p&gt;But, being &lt;del&gt;lazy&lt;/del&gt; all over the place as I am, I went for a simpler solution - running shell commands!&lt;/p&gt;
&lt;p&gt;For this, I am using the &lt;a href="https://github.com/Taitava/obsidian-shellcommands"&gt;Shell Commands&lt;/a&gt; plugin. And since it's not currently possible to export/share the
configuration from it, I'll try and explain the steps I took.&lt;/p&gt;
&lt;p&gt;First, I had to add a custom shell, as Fish (as of April 15th, 2025) is not supported out-of-the-box:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open &lt;a href="obsidian://advanced-uri?settingid=general"&gt;Obsidian settings&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;Navigate to &lt;em&gt;&lt;a href="obsidian://advanced-uri?settingid=obsidian-shellcommands"&gt;Environments -&amp;gt; Custom Shells -&amp;gt; New Custom Shell&lt;/a&gt;&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Shell name: &lt;code&gt;fish&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Executable path: &lt;code&gt;/opt/homebrew/bin/fish&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Then, just for the "configurability" of it, I created a variable for the Hajime directory:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Navigate to &lt;em&gt;&lt;a href="obsidian://advanced-uri?settingid=obsidian-shellcommands"&gt;Variables -&amp;gt; Custom Variables -&amp;gt; New Custom Variable&lt;/a&gt;&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Variable name: &lt;code&gt;hajime_directory&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Description: &lt;code&gt;The directory where your Hajime blog is located&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Default Value: &lt;code&gt;Cancel Execution&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And finally, I created the command itself:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Navigate to &lt;em&gt;&lt;a href="obsidian://advanced-uri?settingid=obsidian-shellcommands"&gt;Shell Commands -&amp;gt; New Shell Command&lt;/a&gt;&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Command: &lt;code&gt;cd {{_hajime_directory}}; hajime sync&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;MacOS Shell: &lt;code&gt;fish&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Variables -&amp;gt; {{_hajime_directory}}&lt;ul&gt;
&lt;li&gt;Execute With Value&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~/dev/blog&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="optional-sourcehut-build"&gt;Optional: Sourcehut Build&lt;a class="headerlink" href="#optional-sourcehut-build" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The cherry on top of my amateur solution is to automate the building process using &lt;a href="https://man.sr.ht/builds.sr.ht/"&gt;Sourcehut Builds&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here's my manifest:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;image: alpine/edge
oauth: pages.sr.ht/PAGES:RW
packages:
  - python3
  - rust
  - uv
  - cargo
  - hut
sources:
  - https://git.sr.ht/~hxii/hajime
environment:
  site: 0xff.nu
tasks:
  - setup: |
      cd hajime
      uv tool install .
  - package: |
      cd $site
      uvx hajime build --compress
      tar -C html -cvz . &amp;gt; ../site.tar.gz
  - upload: |
      hut pages publish -d $site site.tar.gz
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="the-result"&gt;The Result&lt;a class="headerlink" href="#the-result" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I now have one (albeit fairly annoying) excuse less to avoid writing something, as the process is virtually effortless requiring only one command to accomplish.
Probably not elegant, but fuck it! If it's stupid, but it works - it ain't stupid.&lt;/p&gt;</description><pubDate>Tue, 15 Apr 2025 00:00:00 -0000</pubDate></item><item><title>2025 - The year of all the things</title><link>https://0xff.nu/2025-all-the-things/</link><description>&lt;p&gt;On one hand 2025 just started, while on the other -- oh fuck, we're already in April!
The thing for me is, neither of those realizations help with the thought that this year is
way more packed than my ADHD brain anticipated.
Ain't nothing &lt;a class="wikilink" href="/yearly-theme-2025"&gt;focus themed&lt;/a&gt; about this, but it is what it is.&lt;/p&gt;
&lt;p&gt;In all fairness, all of the below probably warrant their own in-depth entry, but I suppose I can at the
very least tl;dr each one. Might as well update my &lt;a class="wikilink" href="/now"&gt;Now&lt;/a&gt; page in the process.&lt;/p&gt;
&lt;h2 id="work"&gt;$Work&lt;a class="headerlink" href="#work" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Learning new development frameworks and packages like &lt;a href="https://tools.slack.dev/bolt-python/"&gt;Slack Bolt&lt;/a&gt; and using them to develop and release a Slack bot.&lt;/li&gt;
&lt;li&gt;Learning to use &lt;code&gt;uv&lt;/code&gt; and &lt;code&gt;mise&lt;/code&gt; more efficiently.&lt;/li&gt;
&lt;li&gt;Learning more about Github Actions and workflows and utilizing them to deploy and build tools in a correct manner.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="personal-projects"&gt;Personal Projects&lt;a class="headerlink" href="#personal-projects" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;FINALLY understanding how to manage my dotfiles, and sharing the settings between my work and personal machines.&lt;/li&gt;
&lt;li&gt;Continuing work on &lt;a class="wikilink" href="/Hajime"&gt;Hajime&lt;/a&gt; while adding support for Obsidian.&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Note:&lt;/strong&gt; There are plenty more items in my backlog.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ordering a &lt;a href="https://docs.usetrmnl.com/"&gt;TRMNL&lt;/a&gt; and developing plugins for it, with a &lt;a href="https://usetrmnl.com/recipes/33478/install"&gt;miniflux plugin&lt;/a&gt; already available and a &lt;a href="https://github.com/mealie-recipes/mealie"&gt;Mealie&lt;/a&gt; soon to be available.&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Note:&lt;/strong&gt; I have like three more projects in my own backlog.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Fucking around with &lt;a href="https://github.com/n8n-io/n8n"&gt;n8n&lt;/a&gt; while creating Todoist enhancements like &lt;a href="https://bsky.app/profile/0xff.nu/post/3ll7fe3o3us2j"&gt;task dependencies&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="life"&gt;Life&lt;a class="headerlink" href="#life" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Packing the entire fucking apartment while getting rid of more useless crap than I ever thought I'd be able to let go of and moving to a bigger, nicer apartment.
  With my burning hatred towards packing, moving and all the stress associated with them, the silver lining is that it does give me the opportunity to throw away all the useless garbage I forget about and re-organize my possessions in a way that makes sense.&lt;/li&gt;
&lt;li&gt;Planning out and sticking to a workout schedule I actually like and brings me results.&lt;/li&gt;
&lt;li&gt;On the way to becoming a father for the second time.&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Tue, 15 Apr 2025 00:00:00 -0000</pubDate></item><item><title>Todoist Wishlist</title><link>https://0xff.nu/todoist-wishlist/</link><description>&lt;p&gt;Todoist is great, but in my humble opinion it is missing some (a few of them basic) features
that could make it that much better. I decided to consolidate them into a list.&lt;/p&gt;
&lt;ul class="checklist"&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Task duration timer - i.e. I thought washing dishes would take me 20 minutes, while it actually took 10.&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Task dependencies/prerequisites - prevent a task from being completed until all sub-tasks have been completed.&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Pin/bookmark task - grouping/sorting aside, some tasks HAVE to be at the top.&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Task status - ability to "pause" a task, for example. Arguably could be addressed via labels.&lt;/li&gt;
&lt;li&gt;iOS Shortcuts&lt;ul class="checklist"&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Get task&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Edit task&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Delete task&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Ability to freely add labels (instead of a predefined list) &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Filters&lt;ul class="checklist"&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Activity filter, e.g. &lt;code&gt;!activity: 7 days&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Aliases for filters&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Regex search, e.g. &lt;code&gt;search:/youtube\.com|youtu\.be/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Grouping&lt;ul class="checklist"&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Grouping by multiple parameters - e.g. &lt;code&gt;group: section, priority&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Grouping by specific labels - e.g. group by &lt;code&gt;@☀️&lt;/code&gt; and &lt;code&gt;@🌙&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Tue, 11 Mar 2025 00:00:00 -0000</pubDate></item><item><title>Yearly Theme 2025</title><link>https://0xff.nu/yearly-theme-2025/</link><description>&lt;p&gt;&lt;img alt="2025 Yearly Theme" src="/2025-theme.png" /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Focus, you fuck!"&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;-- &lt;cite&gt;&lt;a href="https://www.youtube.com/@arduinoversusevil2025"&gt;AvE&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It is that time of the year again for gyms to undergo expensive renovations fueled by the sudden cash influx
caused by three months of "I'm gonna get fit this year" donations.&lt;/p&gt;
&lt;div class="admonition tldr"&gt;
&lt;p class="admonition-title"&gt;TL;DR&lt;/p&gt;
&lt;p&gt;My yearly theme for 2025 - &lt;strong&gt;The Year of Focus.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id="whats-a-yearly-theme"&gt;What's a "Yearly Theme"?&lt;a class="headerlink" href="#whats-a-yearly-theme" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Given that it's already 2025—holy fuck!—I'm assuming some of you might be familiar with the "yearly theme" concept,
but in case you're not - it is a term I first heard from &lt;a href="https://cgpgrey.substack.com/"&gt;CGPGrey&lt;/a&gt; and it goes as follows:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"A Yearly Theme is a word or phrase that represents what you’d like more of in your life, or the direction in which you’d like to go.
A good Theme is broad and acts as a guide, rather than a specific or numerical outcome.
Most importantly – a good theme can’t fail. A broad theme allows you to change.
For example, in The Year of Reading, you may start by reading books and ultimately spend more time reading interesting academic papers – and that’s okay.
If, however, you had set a resolution to “Read 50 books this year”, spending time reading academic journals would have been considered a failure."&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;-- &lt;cite&gt;&lt;a href="https://www.themesystem.com/#:~:text=What%20is%20a%20Yearly%20Theme"&gt;The Theme System Journal&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Another way to look at this (yes, let me get all philosophical for just one fucking minute)
would be through the eyes of stoicism, and specifically the &lt;em&gt;dichotomy of control&lt;/em&gt;.
For me, this is one of the core Stoic principles that I strive to follow at all times.&lt;/p&gt;
&lt;p&gt;What we as mere mortals can control are our thoughts, our actions and our emotions,
while the outcome is completely out of our control (along with other things,
but this is unrelated to my point).&lt;/p&gt;
&lt;p&gt;Let's take the "I'm gonna get fucking fit!" goal as an example - yes, you can go to the gym every
single day, spend your entire income on supplements, read all the guides and
consume all the snake oil on the planet and still not get fit, because as you now understand,
the outcome is not something you can control.
Instead of setting arbitrary (and perhaps unattainable) goals like "I'll lose 20 kilograms" or "I'll read 20 books",
focus on making an effort, no matter how small or large, and learn from your progress.&lt;/p&gt;
&lt;p&gt;Hence, when setting up your yearly theme, don't focus on WHAT you want to achieve,
instead focus on who you want to become or how you want to improve during this time period.&lt;/p&gt;
&lt;p&gt;While specific goals can be useful tools, I guess I'll be &lt;em&gt;that&lt;/em&gt; uncle and remind you, in accordance with Stoicism,
that tying your happiness to achieving your goals (or your unhappiness with missing them)
sets you up for disappointment either way.
Instead, focus on what you can control—your consistent effort and how you respond to challenges.&lt;/p&gt;
&lt;p&gt;Yes, I'm done. No, I'm not fuckin' sorry.&lt;/p&gt;
&lt;h2 id="last-years-theme"&gt;Last Year's Theme&lt;a class="headerlink" href="#last-years-theme" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Last year (which was my first foray into yearly themes), I didn't publicly write about
my chosen theme, but here's the excerpt from my KMS:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The theme for year 2024 shall be: &lt;strong&gt;The year of decluttering and organization&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And while the end of 2023 (and the beginning of 2024) reminded me that the universe
does not give a shit about my plans, I think I did fairly well to stick to the theme,
which ended up being more akin to "The Year of Decluttering, Organization and Restabilizing".&lt;/p&gt;
&lt;h2 id="this-years-theme"&gt;This Year's Theme&lt;a class="headerlink" href="#this-years-theme" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For 2025, my goal is a bit different.
I already started working out (having lost almost 12 kilograms since Jan 2024),
I resumed work on &lt;a href="/hajime"&gt;Hajime&lt;/a&gt; and &lt;a href="/boku"&gt;Boku&lt;/a&gt;, and I am doing well at my actual job.&lt;/p&gt;
&lt;p&gt;So instead of focusing on a single aspect of my life, I am going to follow suit to last
year's theme. The theme for 2025 is - &lt;strong&gt;"The Year of Focus"&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"What the fuck is 'The Year of Focus'?"&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;-- &lt;cite&gt;You, probably.&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I shall explain. Initially, I thought of "The Year of Schedule/ing" as I wanted
to make sure I schedule time to work, read and learn the things I care about (not forgetting
travel and leisure, of course).&lt;/p&gt;
&lt;p&gt;Then I figured that scheduling, while an important and useful tool, is not how this should
be handled, and this is where I kind of combined last year's organization effort together with
this year's &lt;em&gt;ultimate&lt;/em&gt; goal - "make sure I have time to focus on things I care about, one thing at a time",
(which, you have to agree, doesn't make for a good yearly theme title).&lt;/p&gt;
&lt;p&gt;The "how" is not yet fully formed, as some things (like working out) are scheduled, while
for others I will have to counter-act my dumbass, "oh look a squirrel" ADHD brain, e.g.:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Focus on working on/learning one thing at a time.&lt;/li&gt;
&lt;li&gt;Offload other encountered items to my todo list or KMS, instead of getting sidetracked.&lt;/li&gt;
&lt;li&gt;Document my journey and knowledge.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Yearly themes feel like a more humane, flexible approach to personal growth.
It’s only my second year doing this, but I already believe it’s a trend worth continuing.
So go on—decide what matters to you, and let’s do this shit!"&lt;/p&gt;</description><pubDate>Sun, 05 Jan 2025 00:00:00 -0000</pubDate></item><item><title>Expando</title><link>https://0xff.nu/expando/</link><description>&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Salt, Grains and everything in between&lt;/p&gt;
&lt;p&gt;The material presented here should be safe, but you're encouraged to make your own, better implementation.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id="i-was-too-late-i-should-have-been-here-sooner"&gt;"I was too late... I should have been here sooner."&lt;a class="headerlink" href="#i-was-too-late-i-should-have-been-here-sooner" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Some time ago, I came across an interesting concept of text that was very short,
and would expand when you'd click on links to reveal more information.
In my infinite wisdom, I didn't think about saving this groundbreaking concept anywhere
in my black hole of bookmarks so this futuristic information was lost in time, like tears in rain.&lt;/p&gt;
&lt;p&gt;That is until very recently, when I decided to give a little UX makeover to my website's
about/now sections and somehow this gem of internet engineering made its way to my frontal cortex.
I still couldn't remember what it was called, so, in true ADHD fashion,
I embarked on a two-day half-assed quest for this life-changing technology.&lt;/p&gt;
&lt;p&gt;It's time to get cracking. Let's make this dream a reality!&lt;/p&gt;
&lt;p&gt;Eventually, I managed to find a link on HN to a no-longer-working website: &lt;a href="https://telescopictext.com"&gt;https://telescopictext.com&lt;/a&gt;.
I was able to verify that this was indeed the 8th wonder of the world that I was so desperately seeking
for with the help of &lt;a href="https://archive.today"&gt;archive.today&lt;/a&gt;, and I noticed a link to &lt;a href="https://telescopictext.org"&gt;telescopictext.org&lt;/a&gt; down at the bottom.
This helped solidify my relief.&lt;/p&gt;
&lt;h2 id="is-this-really-the-best-you-can-do"&gt;"Is this really the best you can do?"&lt;a class="headerlink" href="#is-this-really-the-best-you-can-do" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;With me being me, the research did not end there, and I've mustered up the mental capacity to scavenge the
internet for other resources and implementations of this downright magical technology:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://basseq.com/fun/telescopictext/"&gt;Telescopic Text&lt;/a&gt; - JavaScript implementation by John Whittet circa... oh boy, 2008.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jackyzha0/telescopic-text"&gt;GitHub - jackyzha0/telescopic-text&lt;/a&gt; - Ah yes, Jacky, the brilliant mind behind &lt;a href="https://github.com/jackyzha0/quartz"&gt;Quartz&lt;/a&gt;! Let's see... oh my god, why is there so much to read? I do like the implementation, though.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://andrewcantino.com/"&gt;Andrew Cantino&lt;/a&gt; - Andrew made this in 2012 and is still using it, what a legend! But it's &lt;code&gt;jQuery&lt;/code&gt; and I'm not gonna use that 😅.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://futuretextlab.info/2024/07/21/telescopic-text/"&gt;Telescopic text – Future Text Lab&lt;/a&gt; - &lt;a href="https://mastodon.social/@Leon@futuretextlab.info"&gt;Leon Van Kammen&lt;/a&gt; made this little gem just recently as well, as it turns out! Still JavaScript, but barely! I mean, just look at it:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class="language-JavaScript"&gt;&amp;lt;script&amp;gt;
    ([...document.querySelectorAll('u')]).map( (u) =&amp;gt; {
        u.addEventListener('click', e =&amp;gt; e.target.className = 'show')
    }
    );
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All of these are nice, but I just... want to make my own, you know? Yeah yeah, typical ADHD behavior -
"How hard can it be?", "It's not going to take much time", "It's for my own fun" yadda yadda yadda.&lt;/p&gt;
&lt;p&gt;And the most important bit - it has to be compatible with my &lt;del&gt;clusterfuck&lt;/del&gt; Markdown-based &lt;a href="/hajime"&gt;website&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="im-going-to-have-to-science-the-shit-out-of-this"&gt;"I’m going to have to science the shit out of this."&lt;a class="headerlink" href="#im-going-to-have-to-science-the-shit-out-of-this" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="the-radio-way"&gt;The &lt;code&gt;radio&lt;/code&gt; way&lt;a class="headerlink" href="#the-radio-way" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;At first, I decided to try a pure HTML/CSS approach using the best hack known to mankind: using inputs.
But instead of using &lt;code&gt;&amp;lt;input type="checkbox"&amp;gt;&lt;/code&gt; we're gonna use it's better brother &lt;code&gt;&amp;lt;input type="radio"&amp;gt;&lt;/code&gt;,
because once clicked (or selected), it can't be unclicked. Sweet.&lt;/p&gt;
&lt;h4 id="html"&gt;HTML&lt;a class="headerlink" href="#html" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code class="language-HTML"&gt;&amp;lt;p&amp;gt;
  My name is &amp;lt;input type=&amp;quot;radio&amp;quot; id=&amp;quot;hxii&amp;quot;&amp;gt;&amp;lt;label for=&amp;quot;hxii&amp;quot; more=&amp;quot;, and I live on planet earth&amp;quot;&amp;gt;hxii&amp;lt;/label&amp;gt;.
&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id="css"&gt;CSS&lt;a class="headerlink" href="#css" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code class="language-CSS"&gt;input[type=&amp;quot;radio&amp;quot;] {
  display: none;
}

input[type=&amp;quot;radio&amp;quot;] + label {
  background: #ddd;
}

input[type=&amp;quot;radio&amp;quot;] + label:hover {
  background: #ccc;
}

input[type=&amp;quot;radio&amp;quot;]:checked + label {
  background: initial;
  padding: 0;
}

input[type=&amp;quot;radio&amp;quot;]:checked + label::after {
  content: attr(more);
  display: inline;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The keen eyed of you will notice I pigeonholed the expansion as an attribute.
We can eliminate the &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; element by using an attribute in the label instead along with some
more CSS wizardry so this just seemed... a bit more streamlined, I guess?&lt;/p&gt;
&lt;p&gt;The issue with this approach - I can't have nested elements, can't use HTML nor can I get this to fucking work in Markdown.&lt;/p&gt;
&lt;h3 id="the-using-things-in-an-illegaly-wrong-way-way-aka-the-a-way"&gt;The "using things in an illegaly wrong way" way, a.k.a the &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; way&lt;a class="headerlink" href="#the-using-things-in-an-illegaly-wrong-way-way-aka-the-a-way" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I apologize in advance, but this brainfart of duct-tape-engineering didn't make its way to the
CodePen demo, because it's hella bork. But I'll share it here:&lt;/p&gt;
&lt;h4 id="html_1"&gt;HTML&lt;a class="headerlink" href="#html_1" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code class="language-HTML"&gt;&amp;lt;p&amp;gt;
  &amp;lt;a href=&amp;quot;#&amp;quot;&amp;gt;Test&amp;lt;/a&amp;gt;&amp;lt;span class=&amp;quot;expansion&amp;quot;&amp;gt; me one more time&amp;lt;/span&amp;gt;.
&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id="css_1"&gt;CSS&lt;a class="headerlink" href="#css_1" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code class="language-CSS"&gt;span.expansion {
  display: none;
}

a:visited+span.expansion {
  display: inline;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Don't use this. &lt;code&gt;visited&lt;/code&gt; links will stay visited and you will stay sad because this doesn't work.&lt;/p&gt;
&lt;h3 id="the-hit-me-with-the-details-way"&gt;The "hit me with the &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt;" way&lt;a class="headerlink" href="#the-hit-me-with-the-details-way" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I am fairly sure the only thing I gained by wasting more time than I potentially should have on this
is more gray hairs. Getting this to work was annoying, as &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; would escape the confines of its
&lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; prison when, since it's a block element. &lt;code&gt;display: inline;&lt;/code&gt; did nothing to help, and &lt;code&gt;Python-Markdown&lt;/code&gt;
wouldn't have it any other way.&lt;/p&gt;
&lt;h4 id="html_2"&gt;HTML&lt;a class="headerlink" href="#html_2" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code class="language-HTML"&gt;&amp;lt;div&amp;gt;
  &amp;lt;span&amp;gt;I own &amp;lt;/span&amp;gt;
  &amp;lt;details&amp;gt;
    &amp;lt;summary&amp;gt;two cats&amp;lt;/summary&amp;gt;a cat named Yoda, and a cat named Pie.
    &amp;lt;details&amp;gt;
      &amp;lt;summary&amp;gt;They are very smart.&amp;lt;/summary&amp;gt;They have maybe two braincells between them, but they're awesome.
    &amp;lt;/details&amp;gt;
  &amp;lt;/details&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The neat thing about this approach, is that I can safely nest these elements and they will work.
I mean, I even spent two days worth of free Claude.ai tokens to make a custom extension for Python-Markdown
and it didn't work.&lt;/p&gt;
&lt;p&gt;Fine, let's just get this over with...&lt;/p&gt;
&lt;h3 id="the-i-have-to-do-this-my-couch-is-counting-on-me-way-aka-the-script-way"&gt;The "I have to do this; my couch is counting on me." way, a.k.a the &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; way&lt;a class="headerlink" href="#the-i-have-to-do-this-my-couch-is-counting-on-me-way-aka-the-script-way" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Look, I didn't wanna go the JavaScript way, alright? But you know how the saying goes...&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“When you’re a spatula and all you see are hammers, it’s time to turn that nail into a spoon—because forks just don’t cut it!”&lt;/p&gt;
&lt;p&gt;-- I didn't sleep too well at night. Sorry.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;How then do I do this without angering mother nature and use the LEAST amount of JavaScript
while keeping this abomination Markdown-safe? Can't do details, links won't work while nested... Lists!&lt;/p&gt;
&lt;p&gt;So the idea is then that all list items will be rendered inline, and any list item with a nested
list after it will roleplay as a text and extended-text. Something like this:&lt;/p&gt;
&lt;h4 id="markdown"&gt;Markdown&lt;a class="headerlink" href="#markdown" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code class="language-Markdown"&gt;- My name
- is hxii
    - is SOMETIMES hxii
- and I like to code
- cool things
    - useless things
    - that look cool
        - that look kinda nice and might be useful
- .
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id="css_2"&gt;CSS&lt;a class="headerlink" href="#css_2" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code class="language-CSS"&gt;div.expando ul {
  display: block;
  margin: 0;
  padding: 0;
}

div.expando ul li {
  display: inline;
}

div.expando li &amp;gt; ul {
  display: none;
}

div.expando li &amp;gt; ul.expanded {
  display: inline;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Fucking wonderful! Now all I have to do is use an HTML block and vomit my Markdown in-between and I'm all set!&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-Markdown"&gt;&amp;lt;div class=&amp;quot;expando&amp;quot; markdown=&amp;quot;1&amp;quot;&amp;gt;
- My terrible professional career as a markdown list.
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A great solution, then.&lt;/p&gt;
&lt;h2 id="the-end"&gt;The End&lt;a class="headerlink" href="#the-end" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It is what it is, and it's not great, but I think it turned out good enough.
It is probably better than my initial idea (which also sparked the &lt;a href="https://git.sr.ht/~hxii/hajime/commit/39c273c"&gt;v0.5 of Hajime&lt;/a&gt;) of adding the
&lt;a href="/now"&gt;now&lt;/a&gt; page with the overflow hidden where the about section now resides.&lt;/p&gt;
&lt;p&gt;You can see the &lt;del&gt;whatever this is&lt;/del&gt; end result, which now takes the shape of the about section on the &lt;a href="/"&gt;main page&lt;/a&gt;.
Here's the &lt;a href="https://codepen.io/nocte/pen/emOONyK"&gt;CodePen link&lt;/a&gt; if you want to play around with the idea.&lt;/p&gt;</description><pubDate>Tue, 26 Nov 2024 00:00:00 -0000</pubDate></item><item><title>About</title><link>https://0xff.nu/about/</link><description>&lt;div class="expando"&gt;
&lt;ul&gt;
&lt;li&gt;I'm&lt;/li&gt;
&lt;li&gt;hxii&lt;ul&gt;
&lt;li&gt;hxii (or Paul Glushak)&lt;/li&gt;
&lt;li&gt;and I'm a&lt;/li&gt;
&lt;li&gt;developer&lt;ul&gt;
&lt;li&gt;Python (previously PHP)&lt;/li&gt;
&lt;li&gt;developer&lt;ul&gt;
&lt;li&gt;developer-ish kinda guy&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;and&lt;/li&gt;
&lt;li&gt;team lead&lt;ul&gt;
&lt;li&gt;R&amp;amp;D Solutions&lt;/li&gt;
&lt;li&gt;team lead&lt;ul&gt;
&lt;li&gt;team lead&lt;/li&gt;
&lt;li&gt;in Forter&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;.&lt;/li&gt;
&lt;li&gt;I like&lt;/li&gt;
&lt;li&gt;making&lt;ul&gt;
&lt;li&gt;ranting, reading and&lt;/li&gt;
&lt;li&gt;making&lt;ul&gt;
&lt;li&gt;trying to make&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;cool&lt;ul&gt;
&lt;li&gt;nice and minimalistic&lt;ul&gt;
&lt;li&gt;sometimes useful and minimalistic&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;things&lt;ul&gt;
&lt;li&gt;little&lt;/li&gt;
&lt;li&gt;projects&lt;ul&gt;
&lt;li&gt;projects like &lt;a class="wikilink" href="/Hajime"&gt;Hajime&lt;/a&gt; and &lt;a class="wikilink" href="/Boku"&gt;Boku&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;.&lt;/li&gt;
&lt;li&gt;Read my &lt;a class="wikilink" href="/now"&gt;Now&lt;/a&gt; page or get in touch via &lt;a href="https://bsky.app/profile/0xff.nu"&gt;bsky&lt;/a&gt; or &lt;a href="https://merveilles.town/@hxii"&gt;Mastodon&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description><pubDate>Mon, 25 Nov 2024 00:00:00 -0000</pubDate></item><item><title>ADHD Productivity Report 2024</title><link>https://0xff.nu/adhd-productivity-2024/</link><description>&lt;h2 id="the-intro"&gt;The Intro&lt;a class="headerlink" href="#the-intro" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After realizing and being able to label the issues I was personally experiencing as ADHD, I finally knew which
information and resources to seek out, which have allowed me to make quite a few adjustments to how
I operate and organize myself and my day-to-day.&lt;/p&gt;
&lt;p&gt;This being said, every so often I try and review the software I use, especially when it comes to &lt;a href="https://0xff.nu/productivity"&gt;productivity with ADHD&lt;/a&gt;,
at the very least to be "in the know" because productivity is an interesting and familiar topic to me,
but also to evaluate potentially better solutions than my current ones.&lt;/p&gt;
&lt;p&gt;I don't often switch between solutions, and my trial periods are perhaps not as in-depth as they should be,
but I am reviewing the software as a power-user with ADHD and a short attention span,
not a professional "product-hunt"er or "productivity guru" with lots of spare time.&lt;/p&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;That's just like, your opinion, man.&lt;/p&gt;
&lt;p&gt;This is not a review, but rather a report on a recent exploration, if you will.
Unfortunately I do not have the time to conduct a full review of each of the apps, and I would suggest you give them a try yourself.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id="the-current-setup"&gt;The Current Setup&lt;a class="headerlink" href="#the-current-setup" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Right now, I utilize the following tools:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Tasks and Reminders - &lt;a href="https://todoist.com/"&gt;Todoist&lt;/a&gt; with a dose of Apple Reminders (because comfort). Does its job well, despite missing some features like start dates or actual/estimate task length.&lt;/li&gt;
&lt;li&gt;Calendar - &lt;a href="https://www.busymac.com/busycal/index.html"&gt;BusyCal&lt;/a&gt; (replaced &lt;a href="https://flexibits.com/fantastical"&gt;Fantastical&lt;/a&gt; following syncing issues I was facing). Again, does its job well, despite some feature discrepancies between desktop and mobile. Not a subscription.&lt;/li&gt;
&lt;li&gt;Personal Email - &lt;a href="https://www.fastmail.com/"&gt;Fastmail&lt;/a&gt; as we prefer not to use Google.&lt;/li&gt;
&lt;li&gt;Work Email - Gmail.&lt;/li&gt;
&lt;li&gt;Bookmarks - &lt;a href="https://raindrop.io/"&gt;Raindrop.io&lt;/a&gt; (evaluating &lt;a href="https://hoarder.app/"&gt;Hoarder&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Knowledge Management and Organization - &lt;a href="https://obsidian.md/"&gt;Obsidian&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;TL;DR&lt;/p&gt;
&lt;p&gt;It seems like we are in a state where everyone (for better or worse) is trying to reinvent the wheel,
handling either tasks or calendars (or both) in their own way, instead of offering a robust,
inclusive and open system to integrate with existing apps and data sources.
Hardly any apps offer Fastmail or CalDAV integration, and virtually none integrate with both&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id="the-culprit"&gt;The Culprit&lt;a class="headerlink" href="#the-culprit" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This time around, what I felt needed reviewing is calendar and task management.
After moving our family calendars to Fastmail, I understood that I needed a solution that will be able to consolidate
information from all three time-sensitive sources mentioned above: Gmail, Fastmail and Todoist.
Hence, my choice fell upon Fantastical, which is able to do just that.&lt;/p&gt;
&lt;p&gt;After experiencing some syncing and usability issues with Fantastical,
I decided to look for potential alternatives that, hopefully, are not going to be subscription based.
Somehow, while looking for alternatives, I came across &lt;a href="https://llamalife.co/"&gt;Llama Life&lt;/a&gt; (which I also realized I've seen before it was widely available)
which labels itself as THE todo app for people with ADHD.&lt;/p&gt;
&lt;p&gt;In true ADHD nature, I immediately forgot about my quest for a calendar and decided to give nice looking camelid a try.
And try I did... for a day, after which I sent a tweet to &lt;a href="https://x.com/llamalife"&gt;@llamalife&lt;/a&gt; (&lt;a href="https://x.com/paulglushak/status/1835200723719520363"&gt;here&lt;/a&gt;) asking if API access was available
because the IMMEDIATE inconvenience for me was the fact that the app is only available on my phone, and nowhere else.
Not on my Apple Watch, PC, work Macbook or even via API (e.g. Raycast, Terminal).
This REQUIRES me to interface with my phone to accomplish anything with the app, which is a major inconvenience
because I do not use my phone all the time.&lt;/p&gt;
&lt;p&gt;The other cons I came across are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It's a web-based app with non-intuitive controls that aren't iOS native (e.g., no slide to delete) and not very intuitive for me.&lt;/li&gt;
&lt;li&gt;Subscription based ($6 monthly, $39 annually). This is generally not a problem, if I feel like there is a legitimate reason for a recurring payment or I feel like I'm getting enough value for my money. In this case, it was a no for both.&lt;/li&gt;
&lt;li&gt;The Todoist integration is not fully baked and is far from frictionless:&lt;/li&gt;
&lt;li&gt;Read-only - LlamaLife does not make changes to Todoist tasks.&lt;/li&gt;
&lt;li&gt;Adding tasks is a manual process, and requires "loading" the tasks into LlamaLife.&lt;/li&gt;
&lt;li&gt;LlamaLife disregards task duration from Todoist.&lt;/li&gt;
&lt;li&gt;No calendar integrations.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I don't mean to dismiss LlamaLife entirely, but at the current point in time it's not a good fit for me.
Oh fuck! Did I mention ADHD already?
Forget the fucking calendar, this brought up a new thought - "Are there other apps that might accomplish what LlamaLife is missing for me?".
Let's jump into testing a lot of different apps, then!&lt;/p&gt;
&lt;p&gt;Short answer - eh... no.&lt;/p&gt;
&lt;h2 id="the-requirements"&gt;The Requirements&lt;a class="headerlink" href="#the-requirements" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In my humble opinion, my ideal requirements don't seem that.. weird - mainly for all my existing tools and sources to be funneled into ONE app.
I don't want to run around juggling and balancing the shitshow that is multiple calendars and todo lists,
and I believe that even if you don't have ADHD, dealing with one app instead of multiple is highly beneficial.
AI assisted scheduling, timers, countdowns and and all that jazz are welcome, but are not a must.
Here's a shopping list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Todoist integration - a service both me and my wife are using.&lt;/li&gt;
&lt;li&gt;Google Calendar integration - work calendar.&lt;/li&gt;
&lt;li&gt;Fastmail/CalDAV integration - personal and family calendar (workaround using Apple Calendar not ideal, but I'll live with it).&lt;/li&gt;
&lt;li&gt;The ability to register and log in with my email, rather than forced reliance on Apple/Google Single Sign-On (SSO).&lt;/li&gt;
&lt;li&gt;Available on &lt;del&gt;three&lt;/del&gt; two platforms: iOS, web &lt;del&gt;and MacOS&lt;/del&gt;. I can live without a native PC/Mac app since the web app retains all the features and runs in my ALREADY-RIGHT-FUCKING-THERE browser. Seriously, I don't want MORE chromium containers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Seems fair, right?&lt;/p&gt;
&lt;h2 id="the-results"&gt;The Results&lt;a class="headerlink" href="#the-results" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It's not easy being &lt;del&gt;cheesy&lt;/del&gt; having basic requirements. Haha 🥲.
With every app that I tried, offered my blood and signed up to a trial (or even paid money for) I felt like my soul
was slowly leaving my body as nothing brought me closer to my end goal.&lt;/p&gt;
&lt;p&gt;This is how it went:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;App&lt;/th&gt;
&lt;th&gt;Integrates with Todoist?&lt;/th&gt;
&lt;th&gt;Integrates with Google Calendar?&lt;/th&gt;
&lt;th&gt;Integrates with FastMail/CalDAV?&lt;/th&gt;
&lt;th&gt;Account&lt;/th&gt;
&lt;th&gt;Platforms&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Notes etc.&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.morgen.so/"&gt;Morgen&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;🟡 Yes but no. Integration not bi-directional. Tasks have to be planned via desktop app. Can't modify tasks, just complete them.&lt;/td&gt;
&lt;td&gt;🟢 Yes&lt;/td&gt;
&lt;td&gt;🟢 Yes&lt;/td&gt;
&lt;td&gt;🟢 Yes&lt;/td&gt;
&lt;td&gt;🔴 No. No web option, although PC/Mac apps are Chromium-based. iOS app is feature-incomplete and not on par with desktop (e.g. no estimates for tasks, unable to plan day)&lt;/td&gt;
&lt;td&gt;$15/month or $9/month annually&lt;/td&gt;
&lt;td&gt;Task estimates have no purpose (i.e. no countdown nor timer). Workflows have to be set up via browser. Why? No Apple Watch companion app.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.usemotion.com/"&gt;Motion&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;🔴 No. &lt;a href="https://www.usemotion.com/blog/stop-using-to-do-list-apps-like-todoist-tick-tick-and-any-do-heres-why#:~:text=Introducing%20Motion%3A%20the%20better%20alternative%20to%20to%2Ddo%20list%20apps"&gt;Suggests Motion replaces it&lt;/a&gt; (yeah no thanks) or to integrate via &lt;a href="https://help.usemotion.com/integrations/integrations-101/integration-guides#motion-less-than-greater-than-todoist"&gt;Zapier&lt;/a&gt;.&lt;/td&gt;
&lt;td&gt;🟢 Yes.&lt;/td&gt;
&lt;td&gt;🔴 No. Apple iCloud as alternative.&lt;/td&gt;
&lt;td&gt;🟢 Yes.&lt;/td&gt;
&lt;td&gt;🔴 ¯\_(ツ)_/¯.&lt;/td&gt;
&lt;td&gt;🤣 $34/month or $20/month annually&lt;/td&gt;
&lt;td&gt;Very fucking expensive. No easily publicly accessible docs. Version history useless. No Apple Watch app.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://amie.so/"&gt;Amie&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;🟡 Yes, but. No assignee filter. No tags. No subtasks.&lt;/td&gt;
&lt;td&gt;🟢 Because of course.&lt;/td&gt;
&lt;td&gt;🔴 No. Apple Calendar as alternative, which doesn't work on Windows \o/.&lt;/td&gt;
&lt;td&gt;🔴 Nope, Google only.&lt;/td&gt;
&lt;td&gt;🟢 Yes, MacOS, Windows, iOS and web.&lt;/td&gt;
&lt;td&gt;$6/month or $5/month annually&lt;/td&gt;
&lt;td&gt;No NLP input. Feature disparity between mobile and desktop. No Apple Watch app. No easily accessible docs. Changelog outdated. Email support unresponsive (6 weeks pending as of Nov. 3rd, 2024)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://ellieplanner.com/"&gt;Ellie Planner&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;🔴 Nope, but &lt;a href="https://feedback.ellieplanner.com/feature-requests/p/todoist-integration"&gt;"coming soon"&lt;/a&gt; (for ~10 months now).&lt;/td&gt;
&lt;td&gt;🟢 Of horse.&lt;/td&gt;
&lt;td&gt;🔴 No. You will not find Apple Calendar salvation here either: "Apple's calendar system doesn't current support 2 way syncing 🥲". And also it's iCloud Calendar which != Apple Calendar.&lt;/td&gt;
&lt;td&gt;🟢 Yes.&lt;/td&gt;
&lt;td&gt;🟢 Yes, MacOS, Windows, iOS and web.&lt;/td&gt;
&lt;td&gt;$10/month or $8.3/month annually&lt;/td&gt;
&lt;td&gt;No Apple Reminders. No Apple Watch app. Has "Estimated Time" which allows enabling a timer, but no Live Activity nor notifications when said timer is running. &lt;a href="https://guide.ellieplanner.com/features/daily-planning-shutdown-rituals"&gt;Daily Planning&lt;/a&gt; not available in iOS. Updating Calendar events not possible.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.offlight.work/"&gt;OFFLIGHT&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;🟢 Yes, but basic. Very basic. I even get tasks assigned to my wife.&lt;/td&gt;
&lt;td&gt;🟢 What do you think?&lt;/td&gt;
&lt;td&gt;🔴 No. No Apple Calendar magic either. &lt;a href="https://offlightinc.featurebase.app/p/caldav-integration"&gt;I filed a request&lt;/a&gt;.&lt;/td&gt;
&lt;td&gt;🔴 No. Google and Apple only.&lt;/td&gt;
&lt;td&gt;🟢 Yes, MacOS, Windows, iOS and web.&lt;/td&gt;
&lt;td&gt;$7/month or $5/month annually&lt;/td&gt;
&lt;td&gt;Has NLP (but basic). Has time tracking (also basic). No Apple Watch app.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.daybridge.com/"&gt;Daybridge&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Fuck knows.&lt;/td&gt;
&lt;td&gt;There has been no updates to this&lt;/td&gt;
&lt;td&gt;From 2022, but it's supposedly still being developed?&lt;/td&gt;
&lt;td&gt;I guess I can keep an eye.&lt;/td&gt;
&lt;td&gt;And review this when I am more mentally vacant to be potentially disappointed.&lt;/td&gt;
&lt;td&gt;Again.&lt;/td&gt;
&lt;td&gt;Or maybe not? I don't know.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://routine.co/"&gt;Routine&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;🔴 No. Fucking even Google Tasks gets priority.&lt;/td&gt;
&lt;td&gt;🟢 Are you even surprised?&lt;/td&gt;
&lt;td&gt;🔴 Nah. &lt;a href="https://x.com/paulglushak/status/1836399160246895021"&gt;"Maybe Q2 2025"&lt;/a&gt;.&lt;/td&gt;
&lt;td&gt;🔴 Lolno. Just Google.&lt;/td&gt;
&lt;td&gt;🟢 MacOS, Windows... web kinda? iOS app hasn't been updated for 5 months.&lt;/td&gt;
&lt;td&gt;$12/month but not yet? 🤷‍♂️&lt;/td&gt;
&lt;td&gt;I don't know.... just feel "eh".&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.risecalendar.com/"&gt;Rise Calendar&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;🔴 Oh you mean Google Tasks?&lt;/td&gt;
&lt;td&gt;🟢 BUSINESS. AND OUTLOOK BECAUSE BUSINESS.&lt;/td&gt;
&lt;td&gt;🔴 What's that? A flavor of Outlook? Even iCloud is &lt;a href="https://support.risecalendar.com/subscribing-to-your-icloud"&gt;"lol share it publicly"&lt;/a&gt; kind of integration.&lt;/td&gt;
&lt;td&gt;🟢 Yes, but what's the point?&lt;/td&gt;
&lt;td&gt;🟢 Yes. I didn't check.&lt;/td&gt;
&lt;td&gt;Free, unless you're a team.&lt;/td&gt;
&lt;td&gt;This feels like a "business or gtfo" type of operation. Headline of &lt;a href="https://www.risecalendar.com/manifesto"&gt;Manifesto&lt;/a&gt; is "It's our mission to help teams get more important work done". What if I'm just me and not a team?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.sunsama.com/"&gt;Sunsama&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;🟢 Yes, with some &lt;a href="https://help.sunsama.com/docs/todoist-troubleshooting-and-faq"&gt;asterisks&lt;/a&gt;.&lt;/td&gt;
&lt;td&gt;🟢 Well yeah.&lt;/td&gt;
&lt;td&gt;🔴 Nope, not even planned. Do businesses even use FastMail or CalDAV? Seriously, this has been requested in &lt;a href="https://roadmap.sunsama.com/integrations/p/caldavicloud-integration"&gt;FUCKING 2019&lt;/a&gt;. iCloud yes.&lt;/td&gt;
&lt;td&gt;🟢 Yes.&lt;/td&gt;
&lt;td&gt;🟢 Yes.&lt;/td&gt;
&lt;td&gt;🤔 $20/month or $16/month annually&lt;/td&gt;
&lt;td&gt;Expensive. Integrates with a bunch of other services. No Apple Watch app. Can't recall if they have a web app.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://akiflow.com/"&gt;Akiflow&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;🟢 Yes.&lt;/td&gt;
&lt;td&gt;🟢 It's green, isn't it?&lt;/td&gt;
&lt;td&gt;🔴 🙅‍♂️. &lt;a href="https://product.akiflow.com/features-and-improvements-request/p/fastmail-integration"&gt;FastMail requested over a year ago&lt;/a&gt;, &lt;a href="https://product.akiflow.com/features-and-improvements-request/p/caldav-calendar-integration"&gt;CalDAV requested three fuckin' years ago&lt;/a&gt; same as &lt;a href="https://product.akiflow.com/features-and-improvements-request/p/icloud-apple-calendar-integration"&gt;APPLE CALENDAR&lt;/a&gt; but hey, let's add AI first yeah?&lt;/td&gt;
&lt;td&gt;🟢 Yes.&lt;/td&gt;
&lt;td&gt;🟢 Yes.&lt;/td&gt;
&lt;td&gt;😅 $34/month or $19/month annually #moneynoobject&lt;/td&gt;
&lt;td&gt;Super expensive (same pricing as Motion. I wonder who's copying who lol). No Apple Watch app.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://structured.app/"&gt;Structured&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;🔴 Nope. This is an Apple club, so only Reminders. So what there's an Android (WIP) version?&lt;/td&gt;
&lt;td&gt;🟡 Through Apple Calendar.&lt;/td&gt;
&lt;td&gt;🟡 Through Apple Calendar.&lt;/td&gt;
&lt;td&gt;🟡 I think so?&lt;/td&gt;
&lt;td&gt;🟢 Yes, but Web is weird. Didn't try it. Uses &lt;a href="https://help.structured.app/en/articles/2050050"&gt;their own sync&lt;/a&gt;.&lt;/td&gt;
&lt;td&gt;$5/month, $1.25/month if paid annually or $50 for "lifetime"&lt;/td&gt;
&lt;td&gt;No timers, only countdowns when focusing on a task.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.tiimoapp.com/"&gt;Tiimo&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;🔴 Hell no, even though it was &lt;a href="https://tiimo.nolt.io/105"&gt;first requested three years ago&lt;/a&gt;.&lt;/td&gt;
&lt;td&gt;🟡 Only on Android. Otherwise it's done through &lt;a href="https://help.tiimoapp.com/ios-features-how-tos/import-calendar-have-all-your-plans-one-place"&gt;Apple Calendar&lt;/a&gt;.&lt;/td&gt;
&lt;td&gt;🟡 Same as the Google Calendar. So... kinda?&lt;/td&gt;
&lt;td&gt;🟢 Yes!&lt;/td&gt;
&lt;td&gt;🟡 &lt;a href="https://tiimo.nolt.io/16"&gt;In progress&lt;/a&gt;.&lt;/td&gt;
&lt;td&gt;$10/month or $3.5/month if paid annually&lt;/td&gt;
&lt;td&gt;No NLP, which is counterproductive to ADHD. No option for a timer, only a countdown. &lt;a href="https://old.reddit.com/r/TiimoApp/comments/1ftt1ke/i_am_so_sorry_to_say_it_but_i_absolutely_hate_the/"&gt;Make&lt;/a&gt; &lt;a href="https://old.reddit.com/r/TiimoApp/comments/1g1h4g4/cant_make_routines/"&gt;questionable&lt;/a&gt; &lt;a href="https://old.reddit.com/r/TiimoApp/comments/1gbh2ur/the_quickest_way_to_lose_ur_entire_user_base/"&gt;changes&lt;/a&gt; &lt;a href="https://old.reddit.com/r/TiimoApp/comments/1gdreu1/my_partner_is_in_tears_over_your_new_update_great/"&gt;directly&lt;/a&gt; against their userbase.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.ticktick.com/"&gt;TickTick&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;🔴 Of course not. It's a competitor. I don't really want to change my to-do app, but let's give it a shot.&lt;/td&gt;
&lt;td&gt;🟡 Yes, but it's super painful. Why do my events are tasks in TickTick? Can't make changes via Mac to local calendar, only on iPhone. Creating new events not possible. Adding attendees not possible either.&lt;/td&gt;
&lt;td&gt;🟢 CalDAV. But I suspect it'll have the same issues as the Google Calendar.&lt;/td&gt;
&lt;td&gt;🟢 Yes!&lt;/td&gt;
&lt;td&gt;🟢 Yup!&lt;/td&gt;
&lt;td&gt;$4/month or $3/month if paid annually&lt;/td&gt;
&lt;td&gt;It's much less known than Todoist, and it shows with their integrations. It's not really a calendar app, and no integration with BusyCal. Task focus timers are cool. Habit tracking. Annoying reminders.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://readdle.com/calendars"&gt;Readdle Calendars&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;🔴 Ha, no. Only Apple Reminders.&lt;/td&gt;
&lt;td&gt;🟢 Well yeah.&lt;/td&gt;
&lt;td&gt;🔴 No. They suggest using Apple Calendar as a workaround.&lt;/td&gt;
&lt;td&gt;🔴 No.&lt;/td&gt;
&lt;td&gt;🔴 What's that? Another Apple Product?&lt;/td&gt;
&lt;td&gt;$1.67/month if paid annually or $60 for "lifetime"&lt;/td&gt;
&lt;td&gt;No subtasks? No task priority? No URL?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.moleskine.com/shop/moleskine-smart/apps-and-services/"&gt;Moleskine&lt;/a&gt; Actions and Timepage&lt;/td&gt;
&lt;td&gt;The apps are interesting and the design is pleasing.&lt;/td&gt;
&lt;td&gt;But they feel very... outlandish and missing the features that are important to me like Todoist.&lt;/td&gt;
&lt;td&gt;Also, no docs, roadmap or anything else. The "Smart Apps" feel like a side gig by them.&lt;/td&gt;
&lt;td&gt;I will keep an eye though.&lt;/td&gt;
&lt;td&gt;Maybe they will improve in the future.&lt;/td&gt;
&lt;td&gt;(from ILS) Separately: $2.67/month or $1.11/month if paid annually. Bundle: $1.87/month annually or $2.98/month annually for a Family account (i.e Family Sharing).&lt;/td&gt;
&lt;td&gt;Let's see!&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="the-bottomline"&gt;The Bottomline&lt;a class="headerlink" href="#the-bottomline" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I am bummed out because I wasn't able to find something that works for me,
but it's cool to see the different paths some of these apps are taking to stand out in this space.&lt;/p&gt;
&lt;p&gt;There are some interesting apps to keep an eye on (OFFLIGHT, Ellie, Amie, &lt;a href="https://www.arcush.com/"&gt;Arcush&lt;/a&gt;,  &lt;a href="https://x.com/LifestackAI"&gt;Lifestack&lt;/a&gt; and others),
but I guess for the time being (as of November 4th, 2024) I will just stick to my "&lt;em&gt;plebeian&lt;/em&gt;"
Todoist + BusyCal combo (with a healthy dose of Apple Reminders + &lt;a href="https://x.com/remindmefaster"&gt;Remind Me Faster&lt;/a&gt;) and put my efforts elsewhere.&lt;/p&gt;
&lt;p&gt;At the very least to me, it feels as if most of the productivity ecosphere is fucking hell-bent on catering
to BUSINESS™ customers first, Google/Outlook users second, and the rest of us on a 'COMING SOON™' basis.
I mean that's where the money is, sure, but still. We are people too.&lt;/p&gt;
&lt;p&gt;Tools are, of course, half the battle. The other half is understanding yourself better, your needs, and how you can work smarter, not harder.&lt;/p&gt;
&lt;p&gt;If you’ve faced (or are facing) a similar struggle, or if you have any recommendations based on your own journey, I’d love to hear from you!
Connect with me via &lt;a href="https://x.com/paulglushak"&gt;Twitter&lt;/a&gt; or &lt;a href="https://merveilles.town/@hxii"&gt;Mastodon&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Mon, 04 Nov 2024 00:00:00 -0000</pubDate></item><item><title>Developers aren't Nerds</title><link>https://0xff.nu/dev-and-nerd/</link><description>&lt;p&gt;&lt;img alt="Confused Person listening to me" src="/confus.png" /&gt;&lt;/p&gt;
&lt;h1 id="are-developers-nerds"&gt;Are Developers Nerds?&lt;a class="headerlink" href="#are-developers-nerds" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;For the longest of time, I was under the impression that developers
and programmers, for the most part, are as or even more so interested
in technology, tools, efficiency and productivity as I am. This came from the
somewhat outdated understanding that the barrier of entry into programming
was mentally taxing and required fucking around with compiling, development
environment et al.&lt;/p&gt;
&lt;p&gt;And while this clearly incorrect preconception has been debunked for a while,
it is only recently that this fucking myth was laid to rest for me.&lt;/p&gt;
&lt;p&gt;After recently conversing with some fellow developers and mentioning LSPs, Vim,
Dotfiles, linters and other, supposedly, common things, I was met with a blank stare.
People, for whom writing code was a calculated decision (many of which have
completed a BSc in Computer Science), just don't give a fuck about what IDE
they use, how much they have to move their hands between their keyboard, or what
colorscheme they use or which fucking terminal they run.&lt;/p&gt;
&lt;h1 id="developers-are-not-neccessarily-nerds"&gt;Developers are NOT (neccessarily) Nerds&lt;a class="headerlink" href="#developers-are-not-neccessarily-nerds" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;It is when I realized (and accepted) that the barrier of entry into development
is now lower than ever, that IDEs are super easy to use and that, for the most
part developers are actually programmers, I understood that (no offense)
programmers are just more skilled monkeys than the rest of us with a keyboard
instead of a grenade.&lt;/p&gt;
&lt;p&gt;They complete their assigned task, in the language they learned and are tasked to
code in without caring about the tools they use, how much they move the mouse
around, staying up-to-date on the latest and greatest HN articles or what new
developments are being made in either their domain or others.&lt;/p&gt;
&lt;p&gt;The reality is that developers and nerds are a venn diagram with varying degrees.&lt;/p&gt;
&lt;h1 id="a-developer-and-a-nerd"&gt;A Developer AND a Nerd&lt;a class="headerlink" href="#a-developer-and-a-nerd" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I'm still learning to accept this fact, and it's funny how, at least internally,
this fact "bothers" me, perhaps because I consider myself to be highly curious
(perhaps due to ADHD) about everything and anything (which is both a blessing
and a fucking curse), thus a developer and a nerd.&lt;/p&gt;
&lt;p&gt;Honestly? It's still wild to me, but then again, on the other hand, I am envious
of others as they work and live and experience bliss that I will not get to
experience - the bliss of not giving a fuck.
I have a tendency to get blackholed into tweaking, which is why I am always
trying to stay mindful of the types of tools I choose.&lt;/p&gt;
&lt;p&gt;For as though as I try and keep the tools I use minimal and functional,
it still requires some fucking around to get them as I want them to behave,
but the other side of the scale seems much scarier to me - accepting, and using,
what to me seem like insane defaults.&lt;/p&gt;
&lt;h1 id="developers-and-nerds"&gt;Developers AND Nerds&lt;a class="headerlink" href="#developers-and-nerds" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The conclusion here, is that I was wrong in my expectations and that while I can
share a new working methodology or Nvim plugin I found with a colleague, I need
to accept the fact they might not even know what I am talking about and that they
absolutely don't give a shit.&lt;/p&gt;
&lt;p&gt;Still, I would probably insist on the fact that if everyone were a bit more
interested in the tools we use, how they work and how they can be improved on
an individual level, we all could collectively benefit in the end.&lt;/p&gt;
&lt;h1 id="epilogue"&gt;Epilogue&lt;a class="headerlink" href="#epilogue" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;To conclude (and clarify), this is not some kind of hot take, or a demeaning
rant or praise towards any group whether you do development as a passion or a
9-to-5 job, nor is the intention to convert you from one group to the other -
you do you, if it makes you happy.&lt;/p&gt;
&lt;p&gt;I don't live in a bubble, and personally I think I slot somewhere in the middle,
given that with some things like themes or colorschemes I usually opt in for
a monochrome variant and rarely customize beyond that, and daily drive an iPhone
the settings of which I rarely modify (After having used an Android and fucking
around with ROMs and Themes for years) yet happy to learn things like NeoVim and
foray into Lua because it looks.. fun.&lt;/p&gt;
&lt;p&gt;So, next time you sit down to code, maybe take a moment to explore a new tool or
tweak your existing setup. Worst case, you might just learn something new or scratch
that hidden itch you didn't know you had and contribute to a more efficient
workflow for everyone with your newfound experience.&lt;/p&gt;</description><pubDate>Fri, 24 May 2024 00:00:00 -0000</pubDate></item><item><title>Now</title><link>https://0xff.nu/now/</link><description>&lt;p&gt;This is a little &lt;a href="https://nownownow.com/about"&gt;now&lt;/a&gt; page, inspired by &lt;a href="https://sive.rs/now"&gt;Derek Sivers&lt;/a&gt; where I share what I am doing at this point in life (I'll try and update this periodically).
Update November 26th, 2024.&lt;/p&gt;
&lt;p&gt;&lt;img alt="me" src="/me.png" /&gt;&lt;/p&gt;
&lt;h2 id="static-the-about-section"&gt;Static (The About Section)&lt;a class="headerlink" href="#static-the-about-section" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My name is Paul Glushak, I go by the pseudonym "hxii". I am a small-web, lightweight tool afficionado. This website is a collection of thoughts and projects by me.
This website is running on &lt;a href="/hajime"&gt;Hajime&lt;/a&gt; and doesn't have any ads or tracking.&lt;/p&gt;
&lt;p&gt;Get in touch via &lt;a href="https://merveilles.town/@hxii"&gt;Mastodon&lt;/a&gt;, &lt;a href="https://twitter.com/paulglushak"&gt;Twitter&lt;/a&gt;, &lt;a href="https://bsky.app/profile/0xff.nu"&gt;BlueSky&lt;/a&gt; or &lt;del&gt;subscribe to my &lt;a href="/feed.xml"&gt;feed&lt;/a&gt;&lt;/del&gt; (Not yet working, sorry! 🙇‍♂️).&lt;/p&gt;
&lt;h2 id="professional-work-stuff"&gt;Professional (Work Stuff)&lt;a class="headerlink" href="#professional-work-stuff" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Working as a R&amp;amp;D Solutions manager and Python developer at Forter.&lt;/li&gt;
&lt;li&gt;Learning and improving as a developer and as a manager through trial and error.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="personal"&gt;Personal&lt;a class="headerlink" href="#personal" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Being a husband and a dad to a 4-year old.&lt;/li&gt;
&lt;li&gt;Working on awesome tools again: &lt;a href="/hajime"&gt;Hajime&lt;/a&gt; and &lt;a href="/boku"&gt;Boku&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Emphasizing, and improving &lt;a href="https://0xff.nu/adhd-productivity-fundamentals"&gt;my own productivity&lt;/a&gt; and well-being through decluttering, documenting and learning, especially following the ADHD diagnosis I've been given.&lt;/li&gt;
&lt;li&gt;Trying to be more social and keeping in touch, while keeping my sanity (IRC, Discord, IRL).&lt;/li&gt;
&lt;li&gt;Learning new skills:&lt;/li&gt;
&lt;li&gt;Code editing in the terminal using &lt;a href="https://github.com/zyedidia/micro"&gt;micro&lt;/a&gt; and nVim.&lt;/li&gt;
&lt;li&gt;Lua to supplement my Python knowledge and to be able to contribute and improve micro.&lt;/li&gt;
&lt;li&gt;CI/CD processes and automation in general.&lt;/li&gt;
&lt;li&gt;Unit testing in Python.&lt;/li&gt;
&lt;li&gt;Ukrainian.&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Sun, 19 May 2024 00:00:00 -0000</pubDate></item><item><title>Boku</title><link>https://0xff.nu/boku/</link><description>&lt;p&gt;&lt;img alt="Boku Header Image" src="boku.png" /&gt;&lt;/p&gt;
&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;p&gt;Boku is still under active development, and some features (those that are intended to be included, that is) are missing.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://asciinema.org/a/IFzd7KtoQtGOAL18ZZVEy49eq"&gt;Demo&lt;/a&gt; | &lt;a href="https://sr.ht/~hxii/boku/"&gt;Source&lt;/a&gt; | &lt;a href="https://todo.sr.ht/~hxii/boku"&gt;Issues and Feature Requests&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="what-is-this"&gt;What is this?&lt;a class="headerlink" href="#what-is-this" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Boku (僕, servant from Japanese) is a simple, sequential YAML task runner written in Python.
While other, most likely much better tools exist that achieve this and much more, the intention
was to create a lightweight tool that can help me with recurring tasks without writing much code
to achieve this.&lt;/p&gt;
&lt;h2 id="why"&gt;Why?&lt;a class="headerlink" href="#why" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The idea was (and remains) to create a simple tool that I can personally use to automate simple tasks
(with some added benefits like dependencies) without having to write code (either bash or python) to achieve this.
It's NOT meant to be a replacement to other, much better and more sophisticated tools, but rather a simple
solution to a simple problem with little to no learning curve, hence a simple YAML based syntax.&lt;/p&gt;
&lt;h2 id="installation"&gt;Installation&lt;a class="headerlink" href="#installation" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can easily install/run boku via tools like &lt;code&gt;pipx&lt;/code&gt; or &lt;code&gt;uv&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Via &lt;code&gt;pipx&lt;/code&gt;: &lt;code&gt;pipx install https://git.sr.ht/~hxii/boku/archive/0.2.0.tar.gz&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Via &lt;code&gt;uv&lt;/code&gt;: &lt;code&gt;uv tool install https://git.sr.ht/~hxii/boku/archive/0.2.0.tar.gz&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;I will figure out a brew formula for this at some point.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id="features"&gt;Features&lt;a class="headerlink" href="#features" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Configure tasks as YAML files.&lt;/li&gt;
&lt;li&gt;Pass in arguments via &lt;code&gt;-a key value&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Pre-set variables via:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;variables:
  my_variable: my value
  ```

- Save output to variables via `save_output: variable_name`.
- Use variables with `${variable_name}`.
- Use environment variables with `${env:ENV_VAR}`.
- Use sensitive variables with `@{variable_name}` or `@{env:secret_env_var}`, which will not print the value in logs.
- Iterate on multiple values via:

```yaml
tasks:
  remove_cache:
    iterate:
      - ~/dev/boku2/*.tmp
      - ~/dev/cache_dev/
    run: rm -r {}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Simple dependencies via:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;tasks:
  my_first_task:
    run: brew update
  my_second_task:
    depends_on: my_first_task
    run: brew upgrade
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Set success return code via &lt;code&gt;success_code: 1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run command &lt;code&gt;on_success&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run command &lt;code&gt;on_failure&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;TODO: Global helper wrappers, e.g.:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;helpers:
- name: telegram_message
  command: &amp;quot;curl -X POST https://api.telegram.org/bot&amp;lt;token&amp;gt;/sendMessage -d 'chat_id=&amp;lt;chat_id&amp;gt;&amp;amp;text=&amp;lt;message&amp;gt;'&amp;quot;
  args:
    - token
    - chat_id
    - message
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;TODO: Allow reading tasks from STDIN or URL.&lt;/li&gt;
&lt;li&gt;TODO: Allow &lt;code&gt;boku global install&lt;/code&gt; from URL.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="full-schema"&gt;Full Schema&lt;a class="headerlink" href="#full-schema" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class="language-YAML"&gt;version: 0.1.0 # Boku version
author: Paul Glushak &amp;lt;hxii@0xff.nu&amp;gt; # Author information
description: This is the description of the task file.

variables:
  my_first_var: &amp;quot;A string value&amp;quot;
  my_second_var: 80085
  my_third_var:
    - &amp;quot;list&amp;quot;
    - &amp;quot;of&amp;quot;
    - &amp;quot;items&amp;quot;
  my_secret_var: &amp;quot;A totally secret value&amp;quot;

tasks: # Dict of tasks
  prerequisite_task:
    description: &amp;quot;Dummy task&amp;quot;
    run: &amp;quot;true&amp;quot;
  my_task:
    description: &amp;quot;Optional description of the task&amp;quot;
    run: echo &amp;quot;{}&amp;quot; # The command to run.
    # If `iterate` is used, the iteration will replace `{}` or be appended to the command.
    working_dir: &amp;quot;~&amp;quot;
    save_output: my_task # Variable name to save the output to
    iterate: my_third_var # List of items to iterate over.
    # Str evaluates to a variable.
    depends_on: # List of successful tasks that this task depends on.
      - prerequisite_task
    success_code: 0 # Which return code do we consider successful
    on_success: echo &amp;quot;Done!&amp;quot; # Command to run if successful
    on_failure: echo &amp;quot;Oh no!&amp;quot; # Command to run if failed
  my_final_task:
    depends_on:
      - my_task
    run: |
      echo &amp;quot;${my_task}&amp;quot; | tr -d '\n'
      echo &amp;quot;We can also use multiline commands&amp;quot;
  my_secret_task:
    run: 'echo &amp;quot;We can also hide secret variables with the @ symbol: @{my_secret_var}&amp;quot;'
    suppress_output: true
&lt;/code&gt;&lt;/pre&gt;</description><pubDate>Tue, 14 May 2024 00:00:00 -0000</pubDate></item><item><title>Making Sense of The Calendar</title><link>https://0xff.nu/calendar-organization/</link><description>&lt;p&gt;I use multiple calendars to separate contexts as well as todo lists to get stuff done, and since I use &lt;a href="https://www.fastmail.com/"&gt;Fantastical&lt;/a&gt; to consolidate all of these sources to a "single window" into my schedule (but also each source separately), not categorizing or writing meeting and block titles properly causes all of them to appear similar, which in turn requires more mental effort as I'd have to look and read the titles to understand the task's importance once I need to do anything with the schedule.&lt;/p&gt;
&lt;p&gt;For the record, I consolidate my personal FastMail calendars (personal and family calendars), work calendars (personal, manager, team mates and group calendars) and &lt;a href="https://todoist.com/"&gt;Todoist&lt;/a&gt; tasks (personal, work and home tasks).&lt;/p&gt;
&lt;p&gt;I devised a simple set of rules, or guidelines to visually encode my schedule so that it is more easily understood in a quick glance without having to go into details.&lt;/p&gt;
&lt;div class="admonition important important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The rules/guidelines are ordered by visual importance.&lt;/li&gt;
&lt;li&gt;The guidelines are not final and are subject to change.&lt;/li&gt;
&lt;li&gt;Color (scale from red to green) and emoji (person, two people, brain) usage are language-less and thus should be universally understood&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h2 id="rules"&gt;Rules&lt;a class="headerlink" href="#rules" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Color coded&lt;/strong&gt; meetings following the concept of &lt;a href="https://en.wikipedia.org/wiki/MoSCoW_method"&gt;MoSCoW Method&lt;/a&gt;. Since the whole meeting "block" is made of this color, it's the first visually distinct and thusly most important thing.&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Red&lt;/strong&gt;: must happen and cannot move, e.g. &lt;code&gt;❌ N/A&lt;/code&gt; when I have to pick up the kid.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Orange&lt;/strong&gt;: should happen, but can move if required. Usually ordinary meetings, periodic meetings.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Yellow&lt;/strong&gt;: would happen, but can move if required. Generally less of a priority. Temporary or non-mandatory meetings.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Green&lt;/strong&gt;: could happen, but can be moved if required. Signifies time blocks, e.g. "Morning Time Block".&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Emoji prefix&lt;/strong&gt; which represents the meeting "type" or "category" and helps when quickly scanning through the schedule without reading the entire title.
  &lt;strong&gt;Important:&lt;/strong&gt; Visually striking emoji such as ⚠️, ❌ or ❗️ should be used sparsely, as their intrinsic visual value is higher than more "neutral" emojis.&lt;ul&gt;
&lt;li&gt;👤 For personal (one on one) meetings.&lt;/li&gt;
&lt;li&gt;👥 For group meetings.&lt;/li&gt;
&lt;li&gt;📆 For recurring (daily, weekly, monthly) meetings.&lt;/li&gt;
&lt;li&gt;🧠 For time blocks (protection).&lt;/li&gt;
&lt;li&gt;🍽️  For meals.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Meeting titles&lt;/strong&gt; should follow some basic rules.&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Meeting types&lt;/strong&gt; before additional information, e.g. &lt;code&gt;Daily - Tech Support&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Periodic meetings&lt;/strong&gt; are denoted as such, e.g &lt;code&gt;Weekly - Paul &amp;amp; Person&lt;/code&gt; in the title.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Personal meetings&lt;/strong&gt; are formatted as &lt;code&gt;&amp;lt;Scheduler&amp;gt; &amp;amp; &amp;lt;Partner&amp;gt;&lt;/code&gt;, e.g. &lt;code&gt;Paul &amp;amp; Person&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="before"&gt;Before&lt;a class="headerlink" href="#before" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img alt="calendar before" src="calendar-before.png" /&gt;&lt;/p&gt;
&lt;h2 id="after"&gt;After&lt;a class="headerlink" href="#after" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img alt="calendar after" src="calendar-after.png" /&gt;&lt;/p&gt;</description><pubDate>Sun, 05 May 2024 00:00:00 -0000</pubDate></item><item><title>Hajime</title><link>https://0xff.nu/hajime/</link><description>&lt;p&gt;&lt;em&gt;Hajime&lt;/em&gt; (previously called Saisho-PY), meaning "beginning" in Japanese, is a simple, slightly opinionated static website generator built with Python.&lt;/p&gt;
&lt;p&gt;It is the spiritual successor and replacement to &lt;a href="/saisho"&gt;Saisho&lt;/a&gt; (which was made in PHP), and is currently still being developed.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Hajime Logo" src="hajime.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://git.sr.ht/~hxii/hajime"&gt;Get it on SourceHut&lt;/a&gt;, &lt;a href="https://todo.sr.ht/~hxii/hajime"&gt;Report a Problem&lt;/a&gt; or &lt;a href="https://lists.sr.ht/~hxii/hajime-discuss"&gt;Get in touch&lt;/a&gt;.&lt;/p&gt;
&lt;div class="admonition important"&gt;
&lt;p class="admonition-title"&gt;Important&lt;/p&gt;
&lt;p&gt;It is important to note a few things, in case you are interested in giving Hajime a spin:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I'm still ironing out kinks as I come across them. If you see anything, please report on &lt;a href="https://todo.sr.ht/~hxii/hajime"&gt;Hajime tracker&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Hajime is coded with certain assumptions, hence the opinionated part. Examples being the template files it uses, date formats or the lack of Markdown or MD extension configuration.&lt;/li&gt;
&lt;li&gt;As of April 19th, 2024, Hajime is not available as a standalone module, but as I use it as part of an automated build on SourceHut, it doesn't bother me. More on this later.&lt;/li&gt;
&lt;li&gt;Hajime is not feature complete, whatever that means in the context of minimalism. Please take this into account.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h2 id="philosophy"&gt;Philosophy&lt;a class="headerlink" href="#philosophy" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;From my personal point of view, the biggest obstacle to writing and sharing (and well, when it comes to productivity in general) is fucking around with themes, plugins and configurations. We often go so deep into the woods while forgetting why we even went there in the first place.&lt;/p&gt;
&lt;p&gt;The less frills and moving parts, the better. From this aspect, Hajime both &lt;em&gt;is&lt;/em&gt; and &lt;em&gt;isn't&lt;/em&gt; feature complete - there is one template, some frontmatter and whatever you write in Markdown format. That's pretty much it.&lt;/p&gt;
&lt;p&gt;Hence, the idea for (or behind) Hajime, is identical to how Saisho was operating -- MD comes in, HTML comes out.&lt;/p&gt;
&lt;p&gt;Keep it simple. Keep it honest. Keep it usable.&lt;/p&gt;
&lt;h2 id="dependencies-and-tooling"&gt;Dependencies and Tooling&lt;a class="headerlink" href="#dependencies-and-tooling" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Hajime&lt;/em&gt; was built with Python 3.12 in mind, albeit it probably will work with &amp;gt;=3.10 as well.
In a gist:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/hukkin/tomli"&gt;Tomli&lt;/a&gt; for TOML configuration.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://click.palletsprojects.com/en/8.1.x/"&gt;Click&lt;/a&gt; for CLI.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.dmulholl.com/docs/ibis/master/"&gt;Ibis&lt;/a&gt; for templates.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://python-markdown.github.io"&gt;Markdown&lt;/a&gt; (with some extensions).
The full list of dependencies is relatively short, and can be seen &lt;a href="https://git.sr.ht/~hxii/hajime/tree/main/item/pyproject.toml"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="usage"&gt;Usage&lt;a class="headerlink" href="#usage" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="installation"&gt;Installation&lt;a class="headerlink" href="#installation" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is basically my &lt;a href="https://git.sr.ht/~hxii/0xff.nu/tree/master/item/.build.yml"&gt;&lt;code&gt;build.yml&lt;/code&gt;&lt;/a&gt; paraphrased:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Clone https://git.sr.ht/~hxii/hajime&lt;/li&gt;
&lt;li&gt;Ideally install this in a venv, e.g. &lt;code&gt;cd hajime; python -m venv .venv; chmod +x .venv/bin/activate; ./.venv/bin/activate&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;make install&lt;/code&gt; to install dependencies.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="using-hajime"&gt;Using Hajime&lt;a class="headerlink" href="#using-hajime" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;python -m hajime init&lt;/code&gt; to create a default configuration file.&lt;/li&gt;
&lt;li&gt;Put your template in &lt;code&gt;template&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Put your content in &lt;code&gt;source&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;python -m hajime build&lt;/code&gt; to generate HTML files.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="templates"&gt;Templates&lt;a class="headerlink" href="#templates" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Hajime relies on three main files existing in the &lt;code&gt;template_folder&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;list.html&lt;/code&gt; - The main index or list of entries.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;page.html&lt;/code&gt; - Entry template.
Given to how &lt;code&gt;ibis&lt;/code&gt; works, you can also have templates split to parts or have conditionals.
Please see the &lt;a href="https://www.dmulholl.com/docs/ibis/master/"&gt;Ibis Documentation&lt;/a&gt; for details.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="entries"&gt;Entries&lt;a class="headerlink" href="#entries" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Markdown syntax, obviously, with the following extensions:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;meta&amp;quot;, # YAML Frontmatter
&amp;quot;wikilinks&amp;quot;, # [[wikilinks]]
&amp;quot;extra&amp;quot;, # Abbrev, attr and def lists, fenced code, footnotes, tables
&amp;quot;admonition&amp;quot;, # rST Style admonitions - https://python-markdown.github.io/extensions/admonition/
&amp;quot;fenced_code&amp;quot;, # As it says
&amp;quot;markdown_mark&amp;quot;, # Marked text
&amp;quot;yafg&amp;quot;, # Figures - https://pypi.org/project/yafg/
&amp;quot;markdown_del_ins&amp;quot;, # Deleted and inserted text
&amp;quot;toc&amp;quot;, # TOC - https://python-markdown.github.io/extensions/toc/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Hajime&lt;/em&gt; uses YAML frontmatter for metadata:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-YAML"&gt;---
title: The page title can be different than it's name.
type: entry, page and project are supported types.
date: YYYY-MM-DD format.
tags: comma,delimited,list,of,tags
description: A text description for things like projects
---
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="automating-the-build"&gt;Automating the Build&lt;a class="headerlink" href="#automating-the-build" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;div class="admonition information"&gt;
&lt;p class="admonition-title"&gt;Going Forward&lt;/p&gt;
&lt;p&gt;In the near future, I'd like to add the &lt;code&gt;sync&lt;/code&gt; functionality (or something similarly named) which will allow for a simpler deployment to &lt;strong&gt;SourceHut specifically&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Perhaps a pre-built &lt;code&gt;.build.yml&lt;/code&gt; file or just clear, simple instructions given how brutally simple it is to just get your content out there using SourceHut.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I currently host my blog on SourceHut, and use Hajime with the following &lt;code&gt;.build.yml&lt;/code&gt; to automatically re-generate and upload my website.
You can take inspiration, and get a similar looking setup for your own blog.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-YAML"&gt;image: alpine/edge
oauth: pages.sr.ht/PAGES:RW
packages:
- hut
- rust
- cargo
- python3
- py3-pip
sources:
  - https://git.sr.ht/~hxii/hajime
environment:
  site: 0xff.nu
tasks:
- setup: |
    cd hajime
    python -m venv .venv
    chmod +x .venv/bin/activate
    ./.venv/bin/activate
    make install
- package: |
    cd $site
    python -m hajime build --compress
    tar -C html -cvz . &amp;gt; ../site.tar.gz
- upload: |
    hut pages publish -d $site site.tar.gz
&lt;/code&gt;&lt;/pre&gt;</description><pubDate>Fri, 19 Apr 2024 00:00:00 -0000</pubDate></item><item><title>New Home on SourceHut</title><link>https://0xff.nu/now-on-sourcehut/</link><description>&lt;p&gt;For the longest time, my blog was self-hosted on a Vultr.com server using &lt;a class="wikilink" href="/saisho"&gt;Saisho&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I decided to freshen things up a bit, by finishing what I started with &lt;a href="https://git.sr.ht/~hxii/saisho-py"&gt;Saisho-PY&lt;/a&gt; (temporary name. I think we need something new!) and moving to a CI/CD (or is it just CD?) workflow on &lt;a href="https://sr.ht/"&gt;Sourcehut&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now, instead of pushing MD files by SSH to my host (yeah yeah, this could've been simpler, I know. Sue me.), I push changes to a repository which runs a build with the new Python iteration of Saisho, which creates the static pages and uploads them! Nice!&lt;/p&gt;
&lt;p&gt;A full write-up regarding the new engine is pending.&lt;/p&gt;</description><pubDate>Mon, 15 Apr 2024 00:00:00 -0000</pubDate></item><item><title>ADHD Productivity Fundamentals</title><link>https://0xff.nu/adhd-productivity-fundamentals/</link><description>&lt;h1 id="preface"&gt;Preface&lt;a class="headerlink" href="#preface" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I'm not some self-proclaimed productivity guru, and this little post is not going to change your life, water your lawn, boost your memory, improve your relations with the opposite sex or revolutionize your productivity.&lt;/p&gt;
&lt;p&gt;It's very easy to get sucked in and get lost in guides, digital gardens, PKMs, workflows, KBs, automations and whatever else is being shared on the YouTubes and Mediums on the internet, to the point that people often forget WHY they started looking into productivity tools to begin with.&lt;/p&gt;
&lt;p&gt;I found something that works for me, especially with some flavor of ADHD and I am sharing this only with the hopes that you will find inspiration, and consequentially your own way of being productive, through what I personally think are the smallest improvements you can do.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The items are inter-connected, so the order does not really matter here.&lt;/p&gt;
&lt;h1 id="write-everything-down"&gt;Write Everything Down&lt;a class="headerlink" href="#write-everything-down" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Our memory, for the most part, is very, very far from perfect, and in today's world of excess information, it's becoming increasingly difficult keeping it all buttoned down without regurgitating or mixing up said information.&lt;/p&gt;
&lt;p&gt;The simplest thing you can do - write &lt;em&gt;everything&lt;/em&gt; down, first. Use whatever is comfortable and quick &lt;em&gt;for you&lt;/em&gt;, and iterate as necessary. Don't go for the shiniest tool in the box - when you need to quickly screw in one screw, you don't bust out your cordless screwdriver with bit storage, you just use that old, passed down, PH-2 Philips screwdriver.&lt;/p&gt;
&lt;h1 id="use-lists"&gt;Use Lists&lt;a class="headerlink" href="#use-lists" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Lists are magical, and I do my best to abide by the list. I find myself often saying this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If it's not on the list, it doesn't exist.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;While this approach may sound a bit dogmatic or rigid, it's only superficial. The intention is not to brush off something that doesn't exist on your list, but to guard your time and attention from new incoming items.
This means that whatever is &lt;em&gt;not&lt;/em&gt; on the list right now, get's added if it needs to be dealt with, but at a delayed due date instead of "now".&lt;/p&gt;
&lt;p&gt;I use Todoist and various lists therein as my universal inbox. An idea I just had? Quickly add to inbox. An interesting link I found? Inbox. Something we need from the store? Inbox that too.&lt;/p&gt;
&lt;h1 id="schedule-it"&gt;Schedule It&lt;a class="headerlink" href="#schedule-it" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This brings me to an equally important point: Schedule time for everything.
Especially with ADHD, we are often time-blind, and seeing as our tools don't impose limits, we keep hoarding things without ever touching them again.&lt;/p&gt;
&lt;p&gt;Not only meetings need to be on your calendar, but also your tasks as well as all the other things you keep telling yourself you're going to deal with or check out. Sure, that article about "Hidden Files in C64 OS" on HackerNews sounds interesting, but &lt;em&gt;when&lt;/em&gt; are you going to read it?
Give it a due date. Put it on the calendar. Let it remember for you.&lt;/p&gt;
&lt;p&gt;I go over the inbox a couple of times a day, and re-route (or review) the items to their intended location and/or time to be dealt with.&lt;/p&gt;
&lt;h1 id="use-the-proper-tool-for-the-job"&gt;Use the Proper Tool for the Job&lt;a class="headerlink" href="#use-the-proper-tool-for-the-job" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I was hesitant whether to include this part, as "proper tools" are incredibly subjective, and people are often hostile and combatant when their fragile ideals of using &lt;strong&gt;The Knowledge-a-tron 5000&lt;/strong&gt; are being challenged by other productivity gurus. Don't use Logseq, Notion or Obsidian because "xXxMegaFamousGuruYoutuberxXx" uses them.
My &lt;em&gt;personal&lt;/em&gt;, brutalist guidelines:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Start (and ideally, stay) simple, explore other or new options (when/if feasible) and iterate on your process.&lt;/strong&gt;
   Using Google Keep and it works for you? Awesome. Only have Apple Reminders? Sure!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use whatever doesn't require (a lot of/often) fuss/noodling/screwing-around to get it to work.&lt;/strong&gt;
   If you need to input a bunch of supplementary information before you can capture your shower thought, perhaps it's not the right tool. Does your tool only work on one out of your ten often used devices without major configuration? Perhaps it's time to find something else.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Get to know your tool and its powers and limitations.&lt;/strong&gt;
   This connects to #1 and #2. Simple tools often have tips and tricks you might not be aware of. Be aware of growth ceilings.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use your tools.&lt;/strong&gt;
   A tool that doesn't get used is ultimately pointless, and is, in fact, worse than not having that tool to begin with.
I personally use Todoist for quick capture and lists, Raindrop for bookmarks and Obsidian for organized information.&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id="simplify"&gt;Simplify&lt;a class="headerlink" href="#simplify" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Simplification doesn't mean becoming a hermit and living in the mountains with no access to the internet and electricity. It simply (ha! get it?) means being aware of your surroundings and making educated choices.
This is arguably the hardest step and includes a few key guidelines.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Remove clutter&lt;/strong&gt; - Something not getting used and won't be used? Get rid of it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduce choice&lt;/strong&gt; - You most likely don't need ten different ways (or apps) to do the same thing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remove noise&lt;/strong&gt; - Remove things (apps/objects) that maliciously fight for your attention.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;a class="headerlink" href="#conclusion" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;Remember &lt;em&gt;why&lt;/em&gt; you are pursuing this.&lt;/li&gt;
&lt;li&gt;Keep things and workflows simple and accessible.&lt;/li&gt;
&lt;li&gt;Tools and opinions are subjective. Give them a try, but keep this in mind.&lt;/li&gt;
&lt;li&gt;Iterate. Become better.&lt;/li&gt;
&lt;/ol&gt;</description><pubDate>Tue, 26 Mar 2024 00:00:00 -0000</pubDate></item><item><title>Productivity with ADHD</title><link>https://0xff.nu/productivity/</link><description>&lt;h2 id="preface"&gt;Preface&lt;a class="headerlink" href="#preface" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We humans, oft have way more things than we need or actually know what to do with. It is something we usually can't (or won't) notice until it's either too late and we realize it ourselves or until someone else points it out to us.&lt;/p&gt;
&lt;p&gt;I recently went through this process again (in retrospect, this happened multiple times throughout the years), except this time, my realization was intertwined with the emotional baggage in relation to being diagnosed (after personally deciding to go through the diagnosis) with ADHD.&lt;/p&gt;
&lt;p&gt;Even though the diagnosis changed very little for me, it was like a breath of fresh air as it gave me perspective on issues of the past (and present) that suddenly received reasoning - things were bothering me before as well, but now I had a potential lead for their cause (or even what might've been amplifying them).&lt;/p&gt;
&lt;p&gt;Then I started noticing the digital (and physical) clutter - I have so, so many things, most of which don't even serve a purpose or are being left unused, yet I kept them either because I thought I was going to use them or due to sentimental value.
All these things, I've noticed, were hindering me and my productivity. I get distracted easily.&lt;/p&gt;
&lt;p&gt;This event sparked change - I was (and am) on a mission to improve myself and my productivity.&lt;/p&gt;
&lt;h2 id="the-possible-solution"&gt;The (possible) Solution&lt;a class="headerlink" href="#the-possible-solution" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What I understood, is that for a workflow to be effective for me, I need to adhere to the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I need to minimize friction as much as possible.&lt;/li&gt;
&lt;li&gt;Create a single point of entry.&lt;/li&gt;
&lt;li&gt;The tools need be accessible from my phone, home PC and the work MacBook.&lt;/li&gt;
&lt;li&gt;If I can combine tools, instead of adding more - even better.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The current iteration for a solution revolves around 4 tools (each of which can be easily replaced by \&lt;insert product name here&gt;):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;To-Do list&lt;/strong&gt; - task planning aside, I use my to-do list as a quick entry point for any new information I need to remember.
   &lt;em&gt;My tool of choice: &lt;a href="https://todoist.com"&gt;Todoist&lt;/a&gt;&lt;/em&gt;.
   &lt;em&gt;Reasoning: Cross-platform, easy input and organization, sharing.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Calendar&lt;/strong&gt; - very important in planning out my day and available time, as I manage both my work and personal calendars as well as any tasks I have to take care of.
   &lt;em&gt;My tool of choice: &lt;a href="https://flexibits.com/fantastical"&gt;Fantastical&lt;/a&gt;&lt;/em&gt;.
   &lt;em&gt;Reasoning: Effortless handling of multiple calendars and lists with minimal input.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bookmarks&lt;/strong&gt; - following an exodus from tab (and bookmark) hell, I've decided to try to &lt;em&gt;actually manage&lt;/em&gt; any bookmarks (and read-it-later items, although these usually end up in my to-do list) I want to keep.
   &lt;em&gt;My tool of choice: &lt;a href="https://raindrop.io"&gt;Raindrop.io&lt;/a&gt;&lt;/em&gt;.
   &lt;em&gt;Reasoning: Sync, cross-platform, management options.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Knowledge Management&lt;/strong&gt; - although I've yet to find a reliable methodology of doing this, I understand that keeping knowledge in an easily accessible form (after processing it, rather than copy-pasting it) is important for now as well as later.
   &lt;em&gt;My tool of choice: &lt;a href="https://obsidian.md"&gt;Obsidian&lt;/a&gt;&lt;/em&gt;.
   &lt;em&gt;Reasoning: Cross-platform, sync, plugins.&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="the-flow"&gt;The Flow&lt;a class="headerlink" href="#the-flow" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Information comes in from multiple sources: wife's request, a work Slack message, interesting find on HN, stumbled across something interesting on the street and so on.&lt;/li&gt;
&lt;li&gt;The input method for &lt;em&gt;unprocessed information&lt;/em&gt; is either directly through Todoist, or through iOS Shortcuts&lt;sup id="fnref:2-1"&gt;&lt;a class="footnote-ref" href="#fn:2-1"&gt;1&lt;/a&gt;&lt;/sup&gt; I've set up on my phone to forward a specific type of information straight to Todoist: song recognition through Shazam, current location, a photo through the camera, a copied link or text or speech-to-text dictation.&lt;/li&gt;
&lt;li&gt;Any processed information (information that I already know what it is or where it goes, in detail) goes into the applicable tool directly:&lt;ul&gt;
&lt;li&gt;Obsidian (knowledge, code snippets)&lt;/li&gt;
&lt;li&gt;Fantastical (meetings, events)&lt;/li&gt;
&lt;li&gt;Raindrop (bookmarks)&lt;/li&gt;
&lt;li&gt;Todoist (if it's a task, or a list item, like a to-buy list).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;I periodically (TBD) go over the Inbox to review items that are there. Items then get transferred to their intended app.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="what-now"&gt;What now?&lt;a class="headerlink" href="#what-now" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This self-proposed, self-utilized solution is definitely not the end goal. My philosophy with the tools I want to use (and create) is for them to be painless and enjoyable to use. A tool is useless if it creates friction, and equally useless if it's not being used.&lt;/p&gt;
&lt;p&gt;I'm trying to make it work, but getting used to, and sometimes forcing yourself to adhere to, a specific workflow after years of essentially "winging it," is not a trivial task.&lt;/p&gt;
&lt;p&gt;I am not afraid of change. I am always on the hunt to make the workflow more efficient and easier for myself, for example I used &lt;a href="https://morgen.so"&gt;Morgen&lt;/a&gt; only for a day to replace it with Fantastical because I had to schedule my tasks AFTER already giving them a due date, or ditching Google Keep for Any.do and now Todoist because of the ease of use and organizational abilities, or buying a subscription to &lt;a href="https://kagi.com"&gt;Kagi&lt;/a&gt; after having a lot of time wasted on DDG, SearXNG and.. Google.&lt;/p&gt;
&lt;p&gt;I want to solve my own issues, not create more of them.&lt;/p&gt;
&lt;p&gt;If you've got any suggestions, get in touch via &lt;a href="https://twitter.com/paulglushak/"&gt;Twitter&lt;/a&gt; or &lt;a href="https://merveilles.town/@hxii"&gt;Mastodon&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="addendum-ios-shortcuts"&gt;Addendum: iOS Shortcuts&lt;a class="headerlink" href="#addendum-ios-shortcuts" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As I've mentioned earlier, unfortunately Todoist's integration with Shortcuts is, at very least currently, lackluster and is missing some basic, and important functionality.
Thus I currently rely on Reminders as a fallback&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:2-1"&gt;
&lt;p&gt;There is currently an unfortunate severe lack of functionality between Todoist and iOS Shortcuts (see this &lt;a href="https://x.com/paulglushak/status/1705901276825821585?s=20"&gt;tweet&lt;/a&gt;) and I find myself sometimes utilizing the native Reminders more than I'd like.&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><pubDate>Tue, 26 Sep 2023 00:00:00 -0000</pubDate></item><item><title>I'm alive</title><link>https://0xff.nu/im-alive/</link><description>&lt;p&gt;I realize it has been a while since I last wrote here, but I am good and well.
Many things have occurred since I last wrote here, most of them good.
I won't go into too much detail, but let's just say that life is improving.&lt;/p&gt;
&lt;h2 id="recent-developments"&gt;Recent Developments&lt;a class="headerlink" href="#recent-developments" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I was diagnosed with some level of ADHD: This explains a lot about me, but also helps me find ways of coping and dealing with this "gift".&lt;/li&gt;
&lt;li&gt;I briefly mentioned this talking about &lt;a class="wikilink" href="/blog/picksy"&gt;Picksy&lt;/a&gt;, but I now work elsewhere, and specifically Forter.
  This was the best career change I have done ever since I left the world of IT. The sole existence of this iteration of &lt;a class="wikilink" href="/Saisho"&gt;Saisho&lt;/a&gt; is owed to the skills (Python) that I gained so far during my time here.&lt;/li&gt;
&lt;li&gt;I learned/ing Python (woo!), but abandoned PHP (boo!).&lt;/li&gt;
&lt;li&gt;Saisho Mk.4 (feat. Python)!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="addadhd"&gt;ADD/ADHD&lt;a class="headerlink" href="#addadhd" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Yeah, so this has been a problem for... a while. Ever since school, but back then nobody (neither me nor my parents) thought that it might be worthwhile to, you know, check the possibility that not everything is right with my brain.
Concentrating on tasks has been difficult, unless the task at hand was particularly interesting to me like videogames, coding, chatting and so on. School was hard :smile:.&lt;/p&gt;
&lt;p&gt;Following the diagnosis (well, actually prior to it as well), I've tried to make some changes to help me cope or live with it. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I tried extending my desire for digital minimalism further by removing unncessary apps from both my computer and phone, disabling non-important notifications, using alterenative apps (Miniflux, Fastmail, Libretube and so on).&lt;/li&gt;
&lt;li&gt;Finding and utilizing organizational tools: Todoist, Raindrop.io, Nota.&lt;/li&gt;
&lt;li&gt;Decluttering my physical space as much as I can, albeit slowly. This change requires time.&lt;/li&gt;
&lt;li&gt;Paying more attention to my body in general and my brain specifically for signs of getting overwhelmed.&lt;/li&gt;
&lt;li&gt;Leaving focus windows for work: reading time, focused work.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="work"&gt;Work&lt;a class="headerlink" href="#work" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I started my new job as a tech support person, and specifically internal tech support. Under my responsibility was the onboarding of new employees, providing them with access and/or credentials to the different apps as well as the development and maintenance of the onboarding script and other related apps and tools.
The description at first didn't seem too glamorous, but it did sound interesting, at the very least because it was quite a bit different than client-facing support. It also came with the promise of "you can make this into your own thing" as what I was about to start didn't really exist before.&lt;/p&gt;
&lt;p&gt;Not long after we hired two more people and I became a team lead/manager. Whoah.
While I was kind of preparing myself to go that direction, I didn't expect for it to happen this soon.
It is super challenging (challenge is &lt;em&gt;definitely&lt;/em&gt; something I need), but also quite satisfying and interesting - there's still lots to learn.&lt;/p&gt;
&lt;h2 id="saisho-mk4"&gt;Saisho Mk.4&lt;a class="headerlink" href="#saisho-mk4" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Saisho is now based on Python, meaning it's a full on SSG instead of a "semi-static" website where the &lt;abbr title="MarkDown"&gt;MD&lt;/abbr&gt; files were generated on the fly.
I also made some small adjustments to the theme of my blog, as you were probably able to tell:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Smaller font.&lt;/li&gt;
&lt;li&gt;Slightly redesigned header.&lt;/li&gt;
&lt;li&gt;Dark/light mode switch.&lt;/li&gt;
&lt;li&gt;Scroll to top button.&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Wed, 10 May 2023 00:00:00 -0000</pubDate></item><item><title>Garlic and Thyme Creamy Sauce Pasta</title><link>https://0xff.nu/garlic-pasta/</link><description>&lt;h2 id="meat"&gt;Meat&lt;a class="headerlink" href="#meat" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I used chicken breast cut into relatively large pieces to make sure it gets marinaded thoroughly.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;In a bowl combine the following:&lt;/li&gt;
&lt;li&gt;Red wine that you like.&lt;/li&gt;
&lt;li&gt;Dried basil.&lt;/li&gt;
&lt;li&gt;Dried thyme.&lt;/li&gt;
&lt;li&gt;Dried oregano.&lt;/li&gt;
&lt;li&gt;Dried garlic powder/granules.&lt;/li&gt;
&lt;li&gt;Salt &amp;amp; pepper.&lt;/li&gt;
&lt;li&gt;Put chicken pieces with the marinade in a sealable bag (i.e. Ziploc), let air out and marinade for at least 1 hour.&lt;/li&gt;
&lt;li&gt;Fry in butter and oil until golden brown.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="vegetables"&gt;Vegetables&lt;a class="headerlink" href="#vegetables" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Boil a large pot of water. Salted.&lt;/li&gt;
&lt;li&gt;Add in relatively small florettes of broccoli and cauliflower.&lt;/li&gt;
&lt;li&gt;Boil for 5 minutes and set aside. Do not discard water.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="sauce"&gt;Sauce&lt;a class="headerlink" href="#sauce" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Fry crudely cut garlic cloves in butter until golden and somewhat crips.&lt;/li&gt;
&lt;li&gt;Take out garlic and set aside.&lt;/li&gt;
&lt;li&gt;Add flour to butter in the pan to make a roux. Once thickened, add dried thyme.&lt;/li&gt;
&lt;li&gt;Add milk and cooking cream (~70ml &amp;amp; 250ml respectively). Add previously removed garlic back.&lt;/li&gt;
&lt;li&gt;Add:&lt;/li&gt;
&lt;li&gt;Half cube of beef stock.&lt;/li&gt;
&lt;li&gt;3 crushed berries of allspice.&lt;/li&gt;
&lt;li&gt;1/2 tsp. nutmeg.&lt;/li&gt;
&lt;li&gt;1/2 tsp. salt &amp;amp; 1/4 tsp. black pepper.&lt;/li&gt;
&lt;li&gt;Make sure everything is mixed and combined properly.&lt;/li&gt;
&lt;li&gt;Let cook for 5 minutes on small flame.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="pasta"&gt;Pasta&lt;a class="headerlink" href="#pasta" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Boil pasta in water used to boil vegetables according to instructions.&lt;/li&gt;
&lt;li&gt;Save 1/4 cup water and discard the rest.&lt;/li&gt;
&lt;li&gt;Add vegetables and sauce.&lt;/li&gt;
&lt;li&gt;Add saved pasta water and mix.&lt;/li&gt;
&lt;/ol&gt;</description><pubDate>Thu, 06 Oct 2022 00:00:00 -0000</pubDate></item><item><title>Stir Fry and Fried Tofu</title><link>https://0xff.nu/stir-fry-and-tofu/</link><description>&lt;p&gt;This is here by request. The recipe is fairly undefined, as the choice is vegetables is mostly up to your likes.&lt;/p&gt;
&lt;h2 id="tofu"&gt;Tofu&lt;a class="headerlink" href="#tofu" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Cut tofu into large cubes, dry by removing water using paper towels and weight applied to tofu.&lt;/li&gt;
&lt;li&gt;Marinade the &lt;em&gt;firm&lt;/em&gt; tofu in a mix of soy sauce, teriyaki sauce, mashed garlic, ginger, salt and pepper from a couple of hours to 2-3 days.&lt;/li&gt;
&lt;li&gt;Drain the marinade and set aside. Prepare a pan with hot unflavored oil for frying.&lt;/li&gt;
&lt;li&gt;Coat the marinated tofu in tempura mix.&lt;/li&gt;
&lt;li&gt;Fry until golden brown and set aside (in a warm place, if possible).&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="vegetables"&gt;Vegetables&lt;a class="headerlink" href="#vegetables" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Examples of vegetables that I use: onion, potato, zucchini, bell pepper, mushrooms, carrot, green beans.
1. Cut vegetables to similar size (except beans, for example). I usually go for 2cm cubes.
2. Fry separately in unflavored oil (you can add some slight flavoring with sesame oil) until half cooked (i.e. not mushy).&lt;/p&gt;
&lt;h2 id="sauce"&gt;Sauce&lt;a class="headerlink" href="#sauce" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Once all vegetables have been fried, add the marinade from the tofu together with a can of crushed tomatoes and about two tablespoons of soy and teriyaki sauce to a wok.&lt;/li&gt;
&lt;li&gt;Once sauce is up to temperature, taste it to make sure it's not too salty (depends on soy and teriyaki). If it is, add some honey or brown sugar to balance it.&lt;/li&gt;
&lt;li&gt;Add all the vegetables to the sauce and cook for 2-3 minutes.&lt;/li&gt;
&lt;li&gt;Add sesame and nigella.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="serving"&gt;Serving&lt;a class="headerlink" href="#serving" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Plain white rice.&lt;/li&gt;
&lt;li&gt;Add vegetables.&lt;/li&gt;
&lt;li&gt;Add fried tofu.&lt;/li&gt;
&lt;/ol&gt;</description><pubDate>Fri, 30 Sep 2022 00:00:00 -0000</pubDate></item><item><title>Picksy</title><link>https://0xff.nu/picksy/</link><description>&lt;h1 id="picksy"&gt;Picksy&lt;a class="headerlink" href="#picksy" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id="preface"&gt;Preface&lt;a class="headerlink" href="#preface" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Seeing as I have not written anything for a little while, a preface, if you will.
Just before 2021 ended, I quit my job as I was unsatisfied with not being able to learn and develop myself. Being stagnant makes me just not enjoy what I do and takes me to dark places, so I prefer to avoid this situation.&lt;/p&gt;
&lt;p&gt;In December 2021 I've joined my new employer, Forter, as a tech support specialist, which, at least as far as the title denotes is about the same thing I've been doing up until now. Even the pay is virtually the same.
So why have I decided to go through this turmoil you ask? Even before I joined, during the interviews, it was made clear to me that the title is one thing, but what I will be able to do and learn in the process is another thing. Basically mkaing up the position as I go type of deal. Great!&lt;/p&gt;
&lt;p&gt;Fast forward about half a year, I've managed to learn a bit about Python to not feel completely lost when I'm looking at code.
As a way to improve my skills and knowledge I've decided to make some things that I would make public for all the world to see - &lt;a href="https://github.com/hxii/vnu"&gt;VNU&lt;/a&gt; and now Picksy.&lt;/p&gt;
&lt;h2 id="what-is-it"&gt;What is it?&lt;a class="headerlink" href="#what-is-it" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As part of a different project I am working on, I've coded a simple choice menu (yes, instead of using something off the internet) in Python. While usable, I immediately thought it could be even better if I had the ability to filter the results.
A quick search on PyPI and GitHub later I wasn't able to find something that offers this functionality, so I did what anyone would do - make my own!&lt;/p&gt;
&lt;p&gt;So Picksy is just that - a picker menu with the ability to filter items. Nothing more, nothing less.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://asciinema.org/a/0BSnVqQ5atUZ5RWP53KRJJhCC"&gt;Demo on Asciinema&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="the-deets"&gt;The Deets&lt;a class="headerlink" href="#the-deets" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The implementation is done via &lt;code&gt;curses&lt;/code&gt;. I'm not sure yet what I think of curses :D&lt;/li&gt;
&lt;li&gt;Picksy accepts a dictionary where the key is the ID and the value is the text shown, e.g:
  &lt;code&gt;{
  "item1": "First Item",
  "item2": "Second Item"
  ...
}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Picksy will also accept a list for the options which will be transformed into a dictionary.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Not Implemented, but remains a possibility&lt;/strong&gt;: Multi choice.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://github.com/hxii/picksy"&gt;Get it on GitHub&lt;/a&gt; or &lt;a href="https://pypi.org/project/picksy/"&gt;Get it on PyPI&lt;/a&gt;&lt;/p&gt;</description><pubDate>Thu, 23 Jun 2022 00:00:00 -0000</pubDate></item><item><title>Making Notes.cx</title><link>https://0xff.nu/notes/</link><description>&lt;p&gt;A couple of days ago I launched my newest project - &lt;a href="https://notes.cx/help"&gt;Notes.cx&lt;/a&gt;, which is a  small tool came to mind while I was in the car with my wife. At the time, I was working (and still am) on &lt;a href="https://diary.by"&gt;Diary.by&lt;/a&gt;, another project of mine, so I asked my wife what would be the chances that she would find use in something like Diary.by.&lt;/p&gt;
&lt;p&gt;My wife mentioned that she is not the kind of person that would keep a diary or a blog, which made me remember another thing that she mentioned not too long ago - that she likes to sometimes write things down to help herself process them better.&lt;/p&gt;
&lt;p&gt;I figured it would be pretty neat if there was an outlet or a void you could shout into, anonymously, just to put your feelings in writing. Either this, or just sharing meeting notes, a temporary article or blog entry that would live for a short period of time before disappearing forever.&lt;/p&gt;
&lt;h2 id="requirements"&gt;Requirements&lt;a class="headerlink" href="#requirements" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The requirements from a project such as this are not plenty and can be put into bullet points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Simple, straightforward experience in creating notes.&lt;/li&gt;
&lt;li&gt;Easily legible notes once rendered without over-the-top styling.&lt;/li&gt;
&lt;li&gt;Notes are to be saved anonymously yet editable to the original author for a limited period of time.&lt;/li&gt;
&lt;li&gt;Notes, like fleeting thoughts, are temporary and are saved for only 24 hours.&lt;/li&gt;
&lt;li&gt;No social aspect - this means no likes, comments, upvotes or otherwise.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="challenges"&gt;Challenges&lt;a class="headerlink" href="#challenges" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Even though this project is less complex than Diary.by (and is fairly simple in general), the requirements pose a few challenges I had to overcome during the creation of it. To name a few:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Making sure the code is robust enough to handle a large amount of visitors poking, prodding and testing the tool (since registering or logging in is not required to create a note).&lt;/li&gt;
&lt;li&gt;Making sure no &lt;abbr title="Personally Identifiable Information"&gt;PII&lt;/abbr&gt; is stored regarding the note author.&lt;/li&gt;
&lt;li&gt;Making sure the UI/UX is not blocking people during creating or reading notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="code"&gt;Code&lt;a class="headerlink" href="#code" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="building-blocks"&gt;Building Blocks&lt;a class="headerlink" href="#building-blocks" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Thankfully, I recently started writing code in a more reusable manner. This practically jump-started the development of this project, as routing and templating at the very least was already dealt with as part of making &lt;a href="/saisho-mk3"&gt;Saisho&lt;/a&gt; and &lt;a href="https://diary.by"&gt;Diary.by&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="anonymousness"&gt;Anonymousness&lt;a class="headerlink" href="#anonymousness" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When a user visits Notes.cx, a temporary random user identifier is created for the author which is hashed using SHA-256 and is saved as a cookie. The key is an MD5 hash of the author's IP address and &lt;code&gt;random_bytes(32)&lt;/code&gt; was used to generate the value for this. The result looks a bit something like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="The cookie that is generated by Notes.cx" src="/i/notes-cookie.png" /&gt;
This hash is then used when creating notes in the database, and looks something like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="How a note appears in the database" src="/i/notes-db.png" /&gt;&lt;/p&gt;
&lt;p&gt;Since the hash is random, if the author removes the cookie that allows the note to be edited, nothing longer ties the author to the note (data-wise. nginx logging still exists), unless the author decides to leave &lt;abbr title="Personally Identifiable Information"&gt;PII&lt;/abbr&gt; on their own accord.&lt;/p&gt;
&lt;h3 id="nonces"&gt;Nonces&lt;a class="headerlink" href="#nonces" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To make sure requests are only sent from the form, I decided to generate a nonce value which is then verified once the note is created.
Since nonces are temporary, I didn't necessarily need the same level of randomness as the user hashes, so a simple letter randomizer was used to create nonces:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-php"&gt;public static function generateID(int $length = 32, ?int $negative = 0) : string {
    $characterSet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $id = '';
    if ($negative &amp;gt; 0) {
        $length = random_int($length - $negative, $length);
    }
    for ($i = 0; $i &amp;lt; $length; $i++) {
        $id .= substr($characterSet, random_int(0, strlen($characterSet)), 1);
    }
    return $id;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The randomly generated nonce is tied to the user hash as an additional measure to make sure the author who created the note is actually the one sending it to the database via the form. If the nonce is verified, it is then deleted and the note is created.&lt;/p&gt;
&lt;h3 id="random-note-id"&gt;Random note ID&lt;a class="headerlink" href="#random-note-id" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The random note identifier is generated using the &lt;code&gt;generateID()&lt;/code&gt; method above, like this: &lt;code&gt;generateID(10, 3)&lt;/code&gt;. This generates a random string between 7 and 10 characters. To make sure no duplicates exist, the generated ID is checked against the database and is generated again in case it already exists.&lt;/p&gt;
&lt;p&gt;To make sure users cannot edit a note with a manually entered identifier (i.e. changing the URL to be https://notes.cx/edit/potato, for example), before the user is redirected to the editor form the generated identifier is saved on the server and is then verified post-redirection (that's why you can also spot a &lt;code&gt;PHPSESSID&lt;/code&gt; cookie).&lt;/p&gt;
&lt;p&gt;There are probably (most likely) better ways to achieve the above, but that's what I could come up with.&lt;/p&gt;
&lt;h3 id="markdown"&gt;Markdown&lt;a class="headerlink" href="#markdown" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I love using Markdown, so I chose to use it with this project as well. As the focus with Notes.cx was it being very lightweight, there is no special editor on the front-end, just a &lt;code&gt;textarea&lt;/code&gt; element.&lt;/p&gt;
&lt;p&gt;To render Markdown, I decided to use the wildly popular Parsedown (along with the Extra and Extended expansions) on the back-end making sure to enable both &lt;code&gt;setSafeMode&lt;/code&gt; and &lt;code&gt;setMarkupEscaped&lt;/code&gt; flags to make sure no HTML is being rendered once the content is parsed.&lt;/p&gt;
&lt;h3 id="purging-old-data"&gt;Purging old data&lt;a class="headerlink" href="#purging-old-data" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To remove old entries, MySQL events are run each hour to remove old notes and each half an hour to remove old nonces. The database is not being backed up, so there is no way to restore the notes once they have been deleted.&lt;/p&gt;
&lt;h2 id="frontend"&gt;Frontend&lt;a class="headerlink" href="#frontend" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="javascript"&gt;JavaScript&lt;a class="headerlink" href="#javascript" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;At first I decided against using JS for anything, but it is currently being used to provide users with the ability to copy the note ID on desktop or open the sharing menu on mobile. That's it.&lt;/p&gt;
&lt;h3 id="css"&gt;CSS&lt;a class="headerlink" href="#css" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I suck at making CSS files look nice and organized, so the entire thing is a mess. The bottom line is that I've decided against styling things excessively, same as with my own website and as with &lt;a href="https://diary.by"&gt;Diary.by&lt;/a&gt;. I refrained from using classes, and instead decided on using semantic HTML and styling the elements to work nicely together.&lt;/p&gt;
&lt;p&gt;After all, the point here is the content by the author, not my stylistic choices.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;a class="headerlink" href="#conclusion" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This was a fun little project that I managed to see to fruition and one which I intend to keep operational with the costs associated hopefully being covered by my other projects, namely Diary.by.&lt;/p&gt;
&lt;p&gt;I shared it on &lt;a href="https://news.ycombinator.com/item?id=27994692"&gt;Hacker News&lt;/a&gt; and &lt;a href="https://www.producthunt.com/posts/notes-cx"&gt;Product Hunt&lt;/a&gt; to gain some feedback and exposure. While there was a lot of poking and prodding, over 1600 notes were written and notes.cx received at least 16.2k unique visitors. According to goaccess, the total transfer for all this was just under 22MB.&lt;/p&gt;</description><pubDate>Sun, 01 Aug 2021 00:00:00 -0000</pubDate></item><item><title>Stoicism</title><link>https://0xff.nu/stoicism/</link><description>&lt;p&gt;&lt;img alt="A gem cannot be polished without friction, nor a man perfected without trials." src="https://0xff.nu/i/stoic.png" /&gt;&lt;/p&gt;
&lt;p&gt;A little while ago, I finished reading a book called &lt;a href="https://www.goodreads.com/book/show/28257707-the-subtle-art-of-not-giving-a-f-ck"&gt;The Subtle Art of Not Giving a Fuck&lt;/a&gt;, which if I'm being honest, I approached because of it's title (and partially because of the "A Counterintuitive Approach to Living a Good Life" subtitle).
My hopes were not high as I was not the type of person to read self-help literature, but I went ahead and read it anyways.&lt;/p&gt;
&lt;p&gt;Well, and sometimes, misplaced profanity aside, I did not imagine this book would help me as much as it did - between the lines written by Mark Manson I found much reflection and parallels with my own life experiences.
It actually helped me begin to understand that there were other ways of doing things as well as help steer my mindset towards a much better and happier place.&lt;/p&gt;
&lt;p&gt;My newfound knowledge and it's daily practice helped me deal with my sometimes overbearing parents, getting fired, looking for a new job, standing my ground, traumatic childbirth and being a parent.&lt;/p&gt;
&lt;p&gt;This was about 2-3 years ago. Since then, I tried my best to stand by certain principles I set for myself and advice given by the book. I have also heard the term "Stoicism" being thrown around, but never understood nor looked into what it means.
About a week ago, before starting my morning walk I was trying to choose a good playlist to listen to. Spotify decided that I need to check out some playlists and podcasts, the first of which was &lt;a href="https://stoic.coffee/"&gt;Stoic Coffee Break&lt;/a&gt;. "Hmm, I've heard this term before" I thought to myself "might as well check it out now".&lt;/p&gt;
&lt;p&gt;After about 3 episodes and well into my 3rd kilometer of walking, I realized - "The Subtle Art of Not Giving a Fuck", while not mentioned anywhere, is like a boiled down version of stoic principles in layman's terms!
Not word for word, of course, but a lot of what is conveyed, turns out has root in stoicism, at least based on what I know now.&lt;/p&gt;
&lt;p&gt;And so, every time I go for my 5km (or more) walk and listen to Erick Cloward explain something about Stoicism, I train not just my body but also my mind.&lt;/p&gt;
&lt;p&gt;While I can't and won't suggest that everyone follow stoic principles, I do want suggest that everyone should at least look into what they are. It may help you the same way it helped me.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Difficulties strengthen the mind, as labor does the body.”&lt;/p&gt;
&lt;p&gt;-- &lt;cite&gt;Seneca&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;</description><pubDate>Mon, 05 Jul 2021 00:00:00 -0000</pubDate></item><item><title>Saisho Mk. 3</title><link>https://0xff.nu/saisho-mk3/</link><description>&lt;div class="admonition danger"&gt;
&lt;p class="admonition-title"&gt;No longer maintained&lt;/p&gt;
&lt;p&gt;This is no longer updated in favor of Saisho MK.4 – see &lt;a class="wikilink" href="/im-alive"&gt;Im Alive&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img alt="Complexity-time graph" src="https://0xff.nu/i/saisho-3.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://0xff.nu/saisho"&gt;Saisho&lt;/a&gt;, the semi-static&lt;sup id="fnref:2-*"&gt;&lt;a class="footnote-ref" href="#fn:2-*"&gt;1&lt;/a&gt;&lt;/sup&gt; website engine, has been through a couple of iterations now, and every time I try and make it better while keeping it as simple as I can (after all, the entire point is to have a CMS that offers minimal resistance in daily usage, little to no upkeep and minimal bloat).&lt;/p&gt;
&lt;p&gt;With each iteration, I manage to learn new things about PHP - more efficient ways of achieving a goal, better methods to use, unified coding standards and so on and implement them in my own code.&lt;/p&gt;
&lt;p&gt;With version 3 of Saisho, I believe I managed to make the entire thing even more simple and robust. For example, earlier I decided to group all of the entries by year. All that was required is to add a grouping function:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-php"&gt;  private static function groupByYear(array &amp;amp;$pages) {
    foreach ($pages as $base=&amp;gt;$page) {
      $year = substr($page['date'], 0, 4);
      $pages[$year][$base] = $page;
      unset($pages[$base]);
    }
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And a tweak to the &lt;code&gt;list.html&lt;/code&gt; template:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;{% foreach ($data_pages as $year=&amp;gt;$pages): %}
&amp;lt;h3&amp;gt;{{ $year }}&amp;lt;/h3&amp;gt;
&amp;lt;ul class=&amp;quot;entrylist&amp;quot;&amp;gt;
  {% foreach ($pages as $link=&amp;gt;$data): %}
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;{{ $link }}&amp;quot;&amp;gt;{{ $data['title'] }}&amp;lt;/a&amp;gt; &amp;amp;mdash; {{ $data['date'] }}&amp;lt;/li&amp;gt;
  {% endforeach; %}
&amp;lt;/ul&amp;gt;
{% endforeach; %}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="the-new-stuff"&gt;The new stuff&lt;a class="headerlink" href="#the-new-stuff" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The reason I don't like using already existing libraries is not because I hate myself, but because writing something of my own, even with significantly less features, teaches me quite a lot about how things work as well as allowing me to tailor everything to my own needs. Saisho Mk.3 is no different.&lt;/p&gt;
&lt;h3 id="routing-mechanism"&gt;Routing mechanism&lt;a class="headerlink" href="#routing-mechanism" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Routing in the previous iteration, while working, was a shit show - adding new static routes or making any sort of changes was just plain annoying and cumbersome at best. For version 3, I used the router I created for &lt;a href="https://0xff.nu/2021-06#plaintext"&gt;Plaintext&lt;/a&gt; as base and made my own as a separate class.&lt;/p&gt;
&lt;p&gt;It's not feature packed and some things &lt;em&gt;definitely&lt;/em&gt; need to be fixed and improved, but it is working for this use case.&lt;/p&gt;
&lt;h3 id="template-system"&gt;Template system&lt;a class="headerlink" href="#template-system" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Back in the first iteration, the HTML was a part of the code which is a big, big no-no. In version 2 I had created simple PHP "templates", which was basically just taking the HTML out of the logic and putting it into a separate file.&lt;/p&gt;
&lt;p&gt;Now, based on the code from &lt;a href="https://codeshack.io/lightweight-template-engine-php/"&gt;Codeshack&lt;/a&gt;, I created a simple template system that should make my life (and maybe yours, if you use Saisho) easier when making changes to the template.&lt;/p&gt;
&lt;h3 id="markdown-parsing"&gt;Markdown parsing&lt;a class="headerlink" href="#markdown-parsing" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I tried parsing Markdown myself, but doing so reliably (at least with my limited knowledge) proved to be pretty much impossible. The code remains (as it's used for the microblog), but I am back to using Parsedown for Markdown parsing.&lt;/p&gt;
&lt;h3 id="logging"&gt;Logging&lt;a class="headerlink" href="#logging" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I have added logging with multiple log levels in order to diagnose loading times and other issues when running Saisho. Hopefully it'll prove useful to those of you who are willing to try Saisho.
Example log&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-log"&gt;[2021-06-29 08:39:02] - DEBUG - INIT Saisho (Saisho-&amp;gt;__construct:93)
[2021-06-29 08:39:02] - DEBUG - Page data/antispam.md loaded - 13.91ms (Saisho::getPageData:27)
[2021-06-29 08:39:02] - DEBUG - Template entry.html requested (Template::view:31)
[2021-06-29 08:39:02] - DEBUG - Loading template entry.html (Template::includes:20)
[2021-06-29 08:39:02] - DEBUG - Including head.html (Template::includes:20)
[2021-06-29 08:39:02] - DEBUG - Loading template head.html (Template::includes:39)
[2021-06-29 08:39:02] - DEBUG - Including style.css (Template::includes:39)
[2021-06-29 08:39:02] - DEBUG - Loading template style.css (Template::includes:39)
[2021-06-29 08:39:02] - DEBUG - Including title.html (Template::includes:20)
[2021-06-29 08:39:02] - DEBUG - Loading template title.html (Template::includes:39)
[2021-06-29 08:39:02] - DEBUG - Including foot.html (Template::includes:20)
[2021-06-29 08:39:02] - DEBUG - Loading template foot.html (Template::includes:39)
[2021-06-29 08:39:02] - DEBUG - Compiling echoes (Template::compileEchoes:45)
[2021-06-29 08:39:02] - DEBUG - Compiling blocks (Template::compileBlocks:46)
[2021-06-29 08:39:02] - DEBUG - Compiling yields (Template::compileYields:47)
[2021-06-29 08:39:02] - DEBUG - Compiling PHP (Template::compilePHP:48)
[2021-06-29 08:39:02] - DEBUG - Saving compiled file /Users/paul/git/saisho_v3/Compiled/entry.php (Template::saveCompiledFile:22)
[2021-06-29 08:39:02] - DEBUG - Serving /Users/paul/git/saisho_v3/Compiled/entry.php (Template::saveCompiledFile:22)
[2021-06-29 08:39:02] - DEBUG - Finished loading template entry.html - 3.01ms (Template::view:31)
[2021-06-29 08:39:02] - DEBUG - Saisho finished - 23.19ms (Saisho-&amp;gt;__construct:93)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="information"&gt;Information&lt;a class="headerlink" href="#information" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I tried making Saisho as simple as possible, but you have to keep in mind that Saisho is not Wordpress (nor any other well-known CMS):
- It does not have a GUI.
- It does not have an installer.
- It does not have a guide.
- It is not super advanced.
- To get it running, knowing some PHP, HTML and CSS is required.
- And last but not least - it's made by an amateur.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If you have any ideas or suggestions on how to improve Saisho, please contact me on &lt;a href="https://twitter.com/paulglushak"&gt;@paulglushak&lt;/a&gt; via Twitter. (until the contact form is back)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;del&gt;Demo&lt;/del&gt; (soon)&lt;/p&gt;
&lt;p&gt;&lt;del&gt;Download&lt;/del&gt; (soon)&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:2-*"&gt;
&lt;p&gt;Not really static anymore. At least not until I bring entry caching back.&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-*" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><pubDate>Sun, 27 Jun 2021 00:00:00 -0000</pubDate></item><item><title>Twenty Twenty-one Mid-year</title><link>https://0xff.nu/2021-06/</link><description>&lt;p&gt;&lt;img alt="0x7e5" src="https://0xff.nu/i/0x7e5.png" /&gt;
Hello reader. It's been a while. Life... you know?&lt;/p&gt;
&lt;p&gt;Not much has changed - parenthood is still exhausting; COVID-19 feels like a distant nightmare, at least to others it seems; we still didn't go on any vacations and a lot of my projects or ideas are yet to be written down (properly).&lt;/p&gt;
&lt;p&gt;It's been hard. It certainly has. But every experience is annealing. Mental state is good. Physical state, however, needs extra work...&lt;/p&gt;
&lt;h2 id="saisho"&gt;Saisho&lt;a class="headerlink" href="#saisho" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The above notwithstanding, a couple of days ago I "finished" writing Mk. 3 of &lt;a href="https://sho.glushak.net/"&gt;Saisho&lt;/a&gt; (sans auxiliaries, except the &lt;a href="https://0xff.nu/microblog"&gt;microblog&lt;/a&gt;) which should hopefully simplify both maintenance and introduction of new features (when required).
I first mentioned this &lt;a href="https://www.linkedin.com/posts/paulglushak_sundaythoughts-motivateyourself-motivation-activity-6794520930732269568-TS_Q"&gt;a month ago&lt;/a&gt; when I already started working on the third revision, only to realize in my pursuit of making things better and simpler I was, in fact, making them more complicated. That code was scrapped (sans router) and now I actually have something. Something better.&lt;/p&gt;
&lt;p&gt;In a gist, everything has been rewritten, but nothing is 100% finished (then again, is it ever 100% finished?):
- New, better, router code.
- "Proper" templates.
- &lt;del&gt;DIY Markdown parser&lt;/del&gt; Never mind. Parsing Markdown with regex is a pyrrhic victory at best. Back to Parsedown.
- Logging.&lt;/p&gt;
&lt;p&gt;I will make a separate post when the code is available publicly.&lt;/p&gt;
&lt;h2 id="plaintext"&gt;Plaintext&lt;a class="headerlink" href="#plaintext" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Yeah, so about that... I kinda forgot about this project, sorry! Truth be told, life did get in the way of my silly personal projects, for better or worse.
I still have plans for this Plaintext, albeit with a slight pivot in direction. All I can say is that Saisho will play a role in its actualization. More on this later.&lt;/p&gt;
&lt;h2 id="toms-data-onion"&gt;Tom's Data Onion&lt;a class="headerlink" href="#toms-data-onion" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A small (and for some - easy) puzzle I decided to take upon myself as a challenge, proved to be a more formidable foe than I initially thought. Unfortunately, progress is currently halted due to the same reason as the above.&lt;/p&gt;
&lt;p&gt;Also, PHP is definitely (probably) not the best language of choice for solving this thing. But that's what I know, at least for now.&lt;/p&gt;
&lt;p&gt;If you're interested in trying it out yourself (and you should), check it out here: &lt;a href="https://www.tomdalling.com/toms-data-onion/"&gt;Tom's Data Onion&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="work"&gt;Work&lt;a class="headerlink" href="#work" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I've been working at [REDACTED] for 8 months now. So far it proved to be not as challenging as I'd like it to be (in the sense of personal development). On the other hand, I believe this helped me figure out the direction I'd like to take the next step in my career in - an internal tool developer.&lt;/p&gt;
&lt;p&gt;This will allow me to stay in the world of support, but also help me get my feet wet in the development world professionally. I guess we'll see how this works out.&lt;/p&gt;
&lt;h2 id="goals"&gt;Goals&lt;a class="headerlink" href="#goals" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A certain Mr. AvE quite correctly said &lt;a href="https://www.youtube.com/watch?v=E7RgtMGL7CA"&gt;setting yourself goals gives you purpose&lt;/a&gt;. Now, these are not unachievable goals but instead interim or short-term goals. They are set so that I can give myself purpose and track my own progress.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pick up Python. PHP is nice (and Ruby is all but forgotten at this point), but I need extra tools in my toolkit.&lt;/li&gt;
&lt;li&gt;Get back to exercising. Early fatherhood, getting sacked and COVID really did a number on me.&lt;/li&gt;
&lt;li&gt;Finish and release at least some projects.&lt;/li&gt;
&lt;li&gt;Read more.&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Thu, 24 Jun 2021 00:00:00 -0000</pubDate></item><item><title>On creating a social network</title><link>https://0xff.nu/social-network/</link><description>&lt;p&gt;&lt;img alt="Features-discourse chart" src="https://0xff.nu/i/socialfeatures.png" /&gt;&lt;/p&gt;
&lt;h2 id="preface"&gt;Preface&lt;a class="headerlink" href="#preface" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After stumbling upon &lt;a href="https://subreply.com/discover"&gt;Subreply&lt;/a&gt; my interest was piqued - do we still have a place for "alternative" social networks? How hard is it creating such a social network? What are the considerations when creating such a piece of software?&lt;/p&gt;
&lt;p&gt;The solution was "simple" - create a social network of my own and try to incorporate what I myself would like to see in such a network.&lt;/p&gt;
&lt;h2 id="start"&gt;Start&lt;a class="headerlink" href="#start" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now, I'm no stranger to PHP having created quite a few small &lt;a href="/projects"&gt;projects&lt;/a&gt; until now, but this was totally different. Here I would have to create something that multiple people can use simultaneously at least in relative comfort and security. Prior to starting, I actually got in touch with &lt;a href="https://lucianmarin.com/"&gt;Lucian Marin&lt;/a&gt; the creator of Subreply hoping to open a discourse and learn from his experience and ideas of creating a "different" social network, alas, he didn't seem interested in sharing his knowledge.&lt;/p&gt;
&lt;p&gt;The first step was to &lt;em&gt;roughly&lt;/em&gt; understand a bunch of &lt;em&gt;what&lt;/em&gt;s:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;What do I want to create?&lt;/li&gt;
&lt;li&gt;What do I want it to look like?&lt;/li&gt;
&lt;li&gt;What requirements does it have?&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="the-general-guidelines"&gt;The general guidelines&lt;a class="headerlink" href="#the-general-guidelines" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The point of this entire endeavour was not necessarily to come up with something revolutionary and never-before-seen, but rather to get some experience creating a piece of software of this complexity.&lt;/p&gt;
&lt;p&gt;The main guidelines (I guess you can call them) or guiding principles of this project were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Focus on discourse.&lt;/strong&gt; This was most likely &lt;em&gt;the&lt;/em&gt; main point of this entire project. This means no images, no likes, shares or anything of that kind.&lt;/li&gt;
&lt;li&gt;Keep it simple code-wise. Simple code is easy to understand and maintain.&lt;/li&gt;
&lt;li&gt;Keep it simple feature-wise. It would be much more beneficial to create a handful of stable and useful features rather than a bunch of half-assed ones.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I took some inspiration from things of the past: forums, shoutboxes, IRC and so on.&lt;/p&gt;</description><pubDate>Mon, 08 Mar 2021 00:00:00 -0000</pubDate></item><item><title>hxii's AntiSpam</title><link>https://0xff.nu/antispam/</link><description>&lt;p&gt;Recently I've finally decided to deal with the spam problem I've been having while using &lt;a href="https://formsubmit.io/"&gt;FormSubmit&lt;/a&gt;.
Despite FormSubmit having their own spam prevention methods, I was still receiving pointless emails from bots using the form:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Example of spam" src="https://0xff.nu/i/Darkslategray-79c80cb8f907aa23.jpg" /&gt;
&lt;img alt="Example of spam no.2" src="https://0xff.nu/i/Skeletal-c73774c817d7400f.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;As banning specific IPs is as effective as chasing your own tail, I've decided to employ a fairly simple concept - a honeypot.
To make it a bit more interesting, and most importantly educational, I've decided to code the solution by myself.&lt;/p&gt;
&lt;h2 id="the-concept"&gt;The Concept&lt;a class="headerlink" href="#the-concept" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As the form I'm using is quite basic (only the comment field is available), I've added a couple of honeypot fields that under no normal circumstance will be filled out by people: name, last name and email:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-HTML"&gt;&amp;lt;input name=&amp;quot;email&amp;quot; id=&amp;quot;email&amp;quot; type=&amp;quot;hidden&amp;quot; value=&amp;quot;&amp;quot;&amp;gt;
&amp;lt;input name=&amp;quot;name&amp;quot; id=&amp;quot;name&amp;quot; type=&amp;quot;text&amp;quot; autocomplete=&amp;quot;off&amp;quot; style=&amp;quot;opacity:0;position:absolute;z-index:-1;top:0;left:0;height:0;width:0&amp;quot; tabindex=&amp;quot;-1&amp;quot;&amp;gt;
&amp;lt;input name=&amp;quot;lastname&amp;quot; id=&amp;quot;lastname&amp;quot; type=&amp;quot;text&amp;quot; autocomplete=&amp;quot;off&amp;quot; style=&amp;quot;opacity:0;position:absolute;z-index:-1;top:0;left:0;height:0;width:0&amp;quot; tabindex=&amp;quot;-1&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: As you can see, I'm using two different methods of hiding the fields - a &lt;code&gt;type="hidden"&lt;/code&gt; field and using CSS. This is to try and maximize the chances of capturing the bots filling out the form.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I wanted to not only prevent these bots from sending me an email when specific fields were filled out, but also provide a way to flag these bots from using the contact form even if the field were not filled out.&lt;/p&gt;
&lt;p&gt;To do this, I use a file that contains &lt;a href="http://wiki.0xff.nu/antispam#example-rules"&gt;filtering rules&lt;/a&gt; that the client goes through every time the form is submitted. &lt;/p&gt;
&lt;p&gt;I also wanted to give falsely flagged people a way to tell me that they've been flagged, so each infraction gets a reference code which I can match against the log.&lt;/p&gt;
&lt;h2 id="the-code"&gt;The Code&lt;a class="headerlink" href="#the-code" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="overview"&gt;Overview&lt;a class="headerlink" href="#overview" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The way the code works is as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PRE"&gt;Page with contact form ---&amp;gt; Redirector ---&amp;gt; FormSubmit
                               | |
                               | |
                            AntiSpam Code
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;The user (or bot) submits the form on any given page.&lt;/li&gt;
&lt;li&gt;The form action is &lt;code&gt;redirector.php&lt;/code&gt; instead of the FormSubmit URL.&lt;/li&gt;
&lt;li&gt;The redirector performs the following actions:&lt;ol&gt;
&lt;li&gt;Asks the AntiSpam code if the user is already banned.&lt;/li&gt;
&lt;li&gt;If the user is not banned, checks if the honeypot fields were filled out and bans them.&lt;/li&gt;
&lt;li&gt;If the user passed, recreates the form with the needed fields and performs a submit action.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;The users comment is sent to FormSubmit.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="filtering-and-identification"&gt;Filtering and identification&lt;a class="headerlink" href="#filtering-and-identification" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The parameters that sent and checked against the rules are:
- User agent.
- IP address.
- Referrer.
- Payload - JSON encoded form fields.
- Signature - MD5 encoded base64 string of IP and UA concatenated.&lt;/p&gt;
&lt;p&gt;If a user that triggered the system doesn't match any of the rules, the signature is automatically added.&lt;/p&gt;
&lt;h3 id="reference"&gt;Reference&lt;a class="headerlink" href="#reference" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Each time a banned user uses the form and is redirected to the error page gets a reference ID: &lt;code&gt;"r$rule-".md5(base64_encode($date.$id));&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In case the user was falsely flagged, this reference ID will allow you to search the entry in the log by the hash and tell you which rule (line number) prevented them from submitting the form.&lt;/p&gt;
&lt;h2 id="the-outro"&gt;The Outro&lt;a class="headerlink" href="#the-outro" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This code is not ideal and (potentially) has many flaws. It is provided as is for educational purposes and may be updated as I learn of new ways to combat this crap.
You can see the entire code on &lt;a href="https://github.com/hxii/AntiSpam"&gt;Github&lt;/a&gt; or &lt;a href="https://git.sr.ht/~hxii/AntiSpam"&gt;Sourcehut&lt;/a&gt; as well as check out some &lt;a href="http://wiki.0xff.nu/antispam#example-rules"&gt;example rules&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In my experience, it's quite effective:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-LOG"&gt;2021-02-28T12:05:43+00:00 (r3-674e131fb162dc4e7ccd6a87028d70f0) - ip:188.213.34.38
2021-02-28T19:45:48+00:00 (r3-7806599467a5432b9a568ad8b800102a) - ip:188.213.34.38
2021-03-01T06:17:45+00:00 (r21-5058982c9c12d90c95b8ac7b65bb1eb7) - ip:157.97.132.45
2021-03-01T22:31:20+00:00 (r3-fac0418d0930a85dca8a071a4e462de2) - ip:93.195.6.226
2021-03-01T22:31:33+00:00 (r3-2d4686639298ab49529283678fa5682b) - ip:93.195.6.226
2021-03-02T19:57:47+00:00 (r22-19a0125fba262757bdc25aa589e87014) - ip:45.141.156.59
2021-03-02T23:48:34+00:00 (r23-8621d510194c9f964b2bb413bdfd242e) - ip:45.141.156.59
2021-03-04T05:12:48+00:00 (r24-d7574c2ccbbd59ef915debaa51b8e00d) - ip:45.12.177.112
2021-03-04T14:15:23+00:00 (r25-8390eeb2234b4ff5ab187c3c13e083ed) - ip:103.197.168.14
&lt;/code&gt;&lt;/pre&gt;</description><pubDate>Wed, 03 Mar 2021 00:00:00 -0000</pubDate></item><item><title>Plaintext - A simple social network</title><link>https://0xff.nu/plaintext/</link><description/><pubDate>Wed, 03 Mar 2021 00:00:00 -0000</pubDate></item><item><title>Picoblog API</title><link>https://0xff.nu/picoblog-api/</link><description>&lt;p&gt;This is a (VERY) simple and rudimentary API for &lt;a href="/picoblog"&gt;Picoblog&lt;/a&gt;. It requires much work so, for now, this page is hidden and will be constantly updated.
&lt;strong&gt;Note:&lt;/strong&gt; If you're planning on using this, take note of the above!&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;&amp;lt;?php

class mblogapi {

    private $key = &amp;quot;YOUR_SUPER_SECRET_KEY_HERE&amp;quot;;

    private $post, $sourceFile;

    public function __construct(string $sourceFile)
    {
        $this-&amp;gt;sourceFile = $sourceFile;
        $this-&amp;gt;post = json_decode(file_get_contents('php://input'));
        $this-&amp;gt;handleRequest();
    }

    private function handleRequest() {
        if ($this-&amp;gt;post-&amp;gt;key === $this-&amp;gt;key) {
            if ($id = $this-&amp;gt;writeEntry()) {
                http_response_code(200);
                header('Content-Type: application/json');
                print(json_encode(['id'=&amp;gt;$id], JSON_PRETTY_PRINT));
            } else {
                http_response_code(500);
            }
        } else {
                print_r(json_encode($this-&amp;gt;post, JSON_PRETTY_PRINT));
            http_response_code(401);
        }
        die();
    }

    private function ret($data) {
        print_r($data);
    }

    private function generateID() {
        return substr(str_shuffle(md5(time())),0,6);
    }

    private function writeEntry() {
        if (is_file($this-&amp;gt;sourceFile)) {
            $id = $this-&amp;gt;generateID();
            $date = gmdate('Y-m-d\TH:i:s\Z');
            $entry = str_replace([&amp;quot;\n&amp;quot;, &amp;quot;\r&amp;quot;], '', $this-&amp;gt;post-&amp;gt;entry);
            $entry = &amp;quot;{$date}   {$id}   {$entry}&amp;quot;;
            $src = fopen($this-&amp;gt;sourceFile, 'r+');
            $dest = fopen('php://temp', 'w');
            fwrite($dest, $entry . PHP_EOL);

            stream_copy_to_stream($src, $dest);
            rewind($dest);
            rewind($src);
            stream_copy_to_stream($dest, $src);

            fclose($src);
            fclose($dest);
            return $id;
        }
        return false;
    }

}

$api = new mblogapi('blog.txt');
&lt;/code&gt;&lt;/pre&gt;</description><pubDate>Mon, 18 Jan 2021 00:00:00 -0000</pubDate></item><item><title>Text Summarization Experiment</title><link>https://0xff.nu/text-summarization/</link><description>&lt;p&gt;This text summarization experiment is(/was?) a small weekend experiment I ended up doing following a small improvement I was trying to do for my &lt;a href="/making-my-own-kms"&gt;KMS project&lt;/a&gt; involving automatically generating tags for each document, which would hopefully improve search results.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; While I do believe it will be clear from what you are about to read, but I will mention this regardless - I have no experience in NLP, linguistics, math and algorithms as well as quite limited experience in programming as a whole. Nevertheless, coding is fun and, a fortiori, so is experimenting with silly things such as the above.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note 2:&lt;/strong&gt; While the results I've been getting are &lt;em&gt;somewhat&lt;/em&gt; accurate (based on my own testing), this code and it's results probably shouldn't be used in anything mission-critical. I am not responsible for bad grades, AI uprising nor any other mishaps following the usage of the code included hereunder.&lt;/p&gt;
&lt;p&gt;There are tools and libraries available online that will do a MUCH better job, but it's just not as fun, is it?&lt;/p&gt;
&lt;h2 id="the-gist-of-it"&gt;The gist of it&lt;a class="headerlink" href="#the-gist-of-it" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The code will accept a text (in plaintext format; no HTML) and will try to summarize it in a given amount of sentences based on simple keyword extraction and scoring "algorithm".&lt;/p&gt;
&lt;h2 id="the-how"&gt;The How&lt;a class="headerlink" href="#the-how" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="keyword-extraction"&gt;Keyword Extraction&lt;a class="headerlink" href="#keyword-extraction" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The process begins with keyword extraction. To do that, we need to break up the entire text by words which I achieve by using this REGEX pattern: &lt;code&gt;/(\b[a-zA-Z'\-]+\b)/&lt;/code&gt;.
After breaking up the text, I process the keyword array in two steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Remove stopwords and&lt;/li&gt;
&lt;li&gt;Merge similar sounding keywords (based on &lt;code&gt;similar_text()&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Post-processing, we need to find the frequency of they keywords and remove singular occurrence keywords from the array as they are most likely not the &lt;em&gt;main&lt;/em&gt; keywords.&lt;/p&gt;
&lt;h3 id="finding-paragraphs-and-sentences"&gt;Finding paragraphs and sentences&lt;a class="headerlink" href="#finding-paragraphs-and-sentences" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To find the most &lt;em&gt;important&lt;/em&gt; bits of the text, we break it down by paragraphs and sentences:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Find paragraphs by breaking text by two consecutive line endings.&lt;/li&gt;
&lt;li&gt;Find sentences for each paragraph using REGEX &lt;code&gt;/[.?!\n]/&lt;/code&gt; (Note: I am aware that there are times where a period "." doesn't end a sentence.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="scoring"&gt;Scoring&lt;a class="headerlink" href="#scoring" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The frequency score of a keyword is a good starting point and preliminary filtering to find the potentially defining keywords of the text.
But how do we find out which sentences and paragraphs of the text are the most important?&lt;/p&gt;
&lt;p&gt;Through trial and error (and some light reading and research) I came up with the following method of doing just that: when we talk about a subject, we tend to mention the same keywords over and over, and usually towards the beginning of a sentence/paragraph.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Find all occurrences of each keyword in each sentence.&lt;/li&gt;
&lt;li&gt;Each occurrence is scored based on it's distance from the beginning of the sentence multiplied by the keyword's frequency score:
  &lt;code&gt;Score = (Length of Sentence - Keyword Position) * Keyword Frequency&lt;/code&gt;
  This means that the further the keyword is from the beginning of the sentence, the lower the score is.&lt;/li&gt;
&lt;li&gt;Sum up all keyword scores into a sentence score.&lt;/li&gt;
&lt;li&gt;Repeat process for each sentence for each paragraph.&lt;/li&gt;
&lt;li&gt;Rearrange all sentences based on the score and their position within the text:
  &lt;code&gt;Final Score = Score * (1 / (Position of Paragraph + Position of Sentence + 1))&lt;/code&gt;
  This is done in line with what I mentioned above that we usually mention the more important things towards the top of a text.&lt;/li&gt;
&lt;li&gt;Sort the sentences in descending order by the score.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="result"&gt;Result&lt;a class="headerlink" href="#result" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After getting the sentences back from the script, we can just output the top X sentences (3, for example).&lt;/p&gt;
&lt;p&gt;The result turned out to be fairly accurate (given the input text is of decent quality) but obviously there's no artificial intelligence nor machine learning involved in the process so the code and/or ideas presented can obviously be improved.&lt;/p&gt;
&lt;p&gt;If you'd like to try it out, a demo is available &lt;a href="/p/ts"&gt;here&lt;/a&gt;.
The code itself is available on &lt;a href="https://github.com/hxii/text_summarizer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Sun, 17 Jan 2021 00:00:00 -0000</pubDate></item><item><title>Image Placeholder DIV</title><link>https://0xff.nu/image-placeholder/</link><description>&lt;p&gt;This is a quick snippet I already wrote about under &lt;a href="/image-optimization#the-js-route"&gt;Image Optimization&lt;/a&gt; but decided to revisit in order to make it totally image-less (in the placeholder state).&lt;/p&gt;
&lt;p&gt;The change, in a gist, lies in using a &lt;code&gt;button&lt;/code&gt; element instead of an &lt;code&gt;img&lt;/code&gt;. The inner text used to present the reader with the dimensions and filesize of the image they are about to load - this will require some server-side code which I may add here in the future.&lt;/p&gt;
&lt;p&gt;You can, at this point, just use a &lt;a href="/image-optimization#the-css-route"&gt;pure CSS solution&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First, we need the button. Note we're using &lt;code&gt;data-src&lt;/code&gt; to store the URL of the image. The text inside the button can be static ("Click to load") or dynamic ("350x150, 10kB").&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-HTML"&gt;&amp;lt;button class=&amp;quot;loadimg&amp;quot; data-src=&amp;quot;https://via.placeholder.com/350x150&amp;quot;&amp;gt;Click To Load 🖼️&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next up is the code that makes it work. This requires a little bit of JS:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-JS"&gt;const images = document.querySelectorAll(&amp;quot;button.loadimg&amp;quot;);
  images.forEach(function(image) {
      image.addEventListener('click', e =&amp;gt; {
        var i = document.createElement('img');
        i.src = e.target.dataset.src;
        document.body.insertBefore(i,image);
        image.removeEventListener('click', e);
        image.remove();
      });
  });
&lt;/code&gt;&lt;/pre&gt;</description><pubDate>Sun, 10 Jan 2021 00:00:00 -0000</pubDate></item><item><title>Saisho Editor</title><link>https://0xff.nu/saisho-edit/</link><description>&lt;p&gt;Saisho Edit is a very simple (in harmony with Saisho) post editor for &lt;a href="/saisho"&gt;Saisho&lt;/a&gt;. The primary purpose is to allow creating and editing new posts from anywhere using the web.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Saisho Editor" src="https://0xff.nu/i/Uneven-146a625df14bd7ad.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Since Saisho itself is a very light engine, the editor follows suit.
For the time being, all Saisho Edit has is:
- Listing all the MD files.
- Load/save functionality.
- A textarea for your writing.
- PHP session auth.&lt;/p&gt;
&lt;p&gt;&lt;del&gt;Get&lt;/del&gt; (Will become available soon)&lt;/p&gt;</description><pubDate>Thu, 07 Jan 2021 00:00:00 -0000</pubDate></item><item><title>End of Twenty Twenty</title><link>https://0xff.nu/end-of-2020/</link><description>&lt;p&gt;2020 is now over. As you might've noticed, I took a brief "break" from writing (and what's worse - creating) to focus on the changes that have happened recently in my life.&lt;/p&gt;
&lt;p&gt;That being said, recently I felt the need to get back to writing (and creating!), and what's better to conclude a year than in writing?&lt;/p&gt;
&lt;p&gt;2020 was, quite possibly, the most bizarre (for the lack of a better adjective) year I've had to experience in recent memory: from intense dread to unimaginable happiness, from shock and little to no sleep to finally feeling like I've got my life back in order. Many things have happened so quickly that it takes a little while to process it all.&lt;/p&gt;
&lt;h2 id="in-a-gist"&gt;In a gist&lt;a class="headerlink" href="#in-a-gist" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I became a dad after very long and somewhat complicated childbirth. Still processing this one.&lt;/li&gt;
&lt;li&gt;Both me and my wife, as is a large chunk of the population, are working from home and are generally around each other 24/7. Thankfully, we have no reasons to fight nor silly disagreements or quarrels. The only friction was caused by the new challenges we have to face being fresh parents.&lt;/li&gt;
&lt;li&gt;I was fired from work. The reasoning I was provided with is that this is because of COVID-19. I think there is a different reason, however.&lt;/li&gt;
&lt;li&gt;I found a new job in a place I thought will be great for me. &lt;a href="https://0xff.nu/job-search-2"&gt;Turns out it wasn't so&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I have been fired again (see above link for details).&lt;/li&gt;
&lt;li&gt;I found a new job, again. This time in a much more interesting place.&lt;/li&gt;
&lt;li&gt;I've done more coding than I've ever done before in my life.&lt;/li&gt;
&lt;li&gt;We sold our car and bought a new, safer vehicle to spend our family trips together in.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="places-ive-visited"&gt;Places I've visited&lt;a class="headerlink" href="#places-ive-visited" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Nowhere. 2020 has been extremely dull as far as travel is concerned, both because of COVID and because of being a fresh parent. I am really hoping for a much better 2021.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="goals"&gt;Goals&lt;a class="headerlink" href="#goals" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Continue learning code. If not for potential future career aspects, then at least because it's fun learning new things.&lt;/li&gt;
&lt;li&gt;Learn to lead. Thankfully, my previous workplaces taught me both what to do and what to never do, but there is still much to learn.&lt;/li&gt;
&lt;li&gt;Continue learning to parent.&lt;/li&gt;
&lt;li&gt;Get back in shape. Lockdowns and, honestly, lack of time wreaked havoc on my potato body.&lt;/li&gt;
&lt;li&gt;Travel.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Best, and worst day of my life" src="https://0xff.nu/i/Worst-14191ffb1683dd73.jpeg" /&gt;&lt;/p&gt;</description><pubDate>Wed, 06 Jan 2021 00:00:00 -0000</pubDate></item><item><title>The quest for a job in 2020, Part 2</title><link>https://0xff.nu/job-search-2/</link><description>&lt;p&gt;It seems like I was looking for a new job &lt;a href="/job-search"&gt;just recently&lt;/a&gt;, and somehow to my dismay, I found myself doing the exact same thing, again, just last week.&lt;/p&gt;
&lt;p&gt;Now, I'm not one to tattle, so in order to save face, I won't divulge the details of this experience (for the lack of a better title), so let's just say the job... didn't quite fit neither party.
In hindsight, some of the red flags were there from the beginning while some had to be unearthed, but I'm glad this was done sooner than later.&lt;/p&gt;
&lt;p&gt;While some of my time was wasted on this excursion, not all is bad since a very important lesson was learned in this short period of time. It is only unfortunate that this lesson was learned at my own expense.&lt;/p&gt;
&lt;p&gt;Thankfully I've already found something better, with good prospects.&lt;/p&gt;
&lt;p&gt;To new beginnings! &lt;/p&gt;</description><pubDate>Mon, 19 Oct 2020 00:00:00 -0000</pubDate></item><item><title>URL Shortener</title><link>https://0xff.nu/url-shortener/</link><description>&lt;p&gt;File: &lt;code&gt;index.php&lt;/code&gt;
Updated: 2020-10-10&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;&amp;lt;?php

namespace hxii;

class fdb
{

    private $filename, $database, $prefix;

    private $dbHeader = '&amp;lt;?php header(&amp;quot;HTTP/1.0 404 Not Found&amp;quot;);die(); ?&amp;gt;'.PHP_EOL;

    private $authkey = '79A69C0D4B9DFCD94B1BF72799E334D0CC4D1972';

    public function __construct(string $filename, string $prefix)
    {
        $this-&amp;gt;filename = $filename;
        $this-&amp;gt;prefix = $prefix;
        $this-&amp;gt;readDatabase();
    }

    private function initializeDatabase()
    {
        return file_put_contents($this-&amp;gt;filename, $this-&amp;gt;dbHeader);
    }

    private function readDatabase()
    {
        $this-&amp;gt;database = [];
        if (!file_exists($this-&amp;gt;filename)) {
            $this-&amp;gt;initializeDatabase();
        }
        $rawDatabase = array_slice(file($this-&amp;gt;filename), 1);
        foreach ($rawDatabase as $entry) {
            $entry = explode(' ', $entry);
            $this-&amp;gt;database[$entry[0]] = trim($entry[1]);
        }
    }

    private function updateDatabase()
    {
        $fh = fopen($this-&amp;gt;filename, 'w');
        fwrite($fh, $this-&amp;gt;dbHeader);
        foreach ($this-&amp;gt;database as $key =&amp;gt; $url) {
            fwrite($fh, &amp;quot;{$key} {$url}&amp;quot; . PHP_EOL);
        }
        fclose($fh);
    }

    private function parseRequest()
    {
        $request['request'] = trim($_SERVER['REQUEST_URI'],'/');
        $request['query'] = $_POST;
        if (isset($request['query']['key'])) {
            $request['query']['key'] = $this-&amp;gt;prefix.$request['query']['key'];
        }
        return $request;
    }

    public function matchRequest() {
        $request = $this-&amp;gt;parseRequest();
        $command = str_replace('@','',$request['request']).'Entry';
        if (is_callable([$this, $command]) &amp;amp;&amp;amp; $this-&amp;gt;validate()) {
            call_user_func_array([$this, $command], [$request['query']]);
        } else {
            $this-&amp;gt;doRedirect($request['request']);
        }
    }

    private function isAuthenticated()
    {
        return isset($_SERVER['PHP_AUTH_PW']) &amp;amp;&amp;amp; $this-&amp;gt;authkey === $_SERVER['PHP_AUTH_PW'];
    }

    private function validate()
    {
        if (!$this-&amp;gt;isAuthenticated()) {
            http_response_code(401);
            die();
        }
        return true;
    }

    private function doesEntryExist(string $entrykey)
    {
        return array_key_exists($entrykey, $this-&amp;gt;database);
    }

    private function addEntry(array $entry)
    {
        $entry['key'] = $entry['key'] ?? $this-&amp;gt;generateID();
        $this-&amp;gt;database[$entry['key']] = $entry['loc'];
        $this-&amp;gt;updateDatabase($this-&amp;gt;database);
    }

    private function updateEntry(array $entry)
    {
        if ($this-&amp;gt;doesEntryExist($entry['key'])) {
            $this-&amp;gt;database[$entry['key']] = $entry['loc'];
            $this-&amp;gt;updateDatabase($this-&amp;gt;database);
        }
    }

    private function removeEntry(array $entry)
    {
        if ($this-&amp;gt;doesEntryExist($entry['key'])) {
            unset($this-&amp;gt;database[$entry['key']]);
            $this-&amp;gt;updateDatabase($this-&amp;gt;database);
        }
    }

    private function listEntry()
    {
        $this-&amp;gt;response($this-&amp;gt;database);
    }

    private function generateID(int $length = 3)
    {
        $id = str_shuffle(base64_encode(microtime()));
        return $this-&amp;gt;prefix.substr($id, 0, $length);
    }

    private function doRedirect(string $key)
    {
        if ($this-&amp;gt;doesEntryExist($key)) {
            header(&amp;quot;Location: {$this-&amp;gt;database[$key]}&amp;quot;, true, 301);
        } else {
            http_response_code(404);
            die();
        }
    }

    private function response($responseBody)
    {
        header('Content-Type: application/json');
        echo json_encode($responseBody, JSON_PRETTY_PRINT);
    }
}

$fdb = new fdb('db.php', '@');
$fdb-&amp;gt;matchRequest();
&lt;/code&gt;&lt;/pre&gt;</description><pubDate>Sat, 10 Oct 2020 00:00:00 -0000</pubDate></item><item><title>How-to: Creating a super simple URL shortening service</title><link>https://0xff.nu/howto-shortener/</link><description>&lt;p&gt;You know how they say the best way to learn something is to teach it?
I personally don't have time to participate in something like &lt;a href="https://www.100daysofcode.com/"&gt;100 days of code&lt;/a&gt; or anything similar, but that doesn't mean that I shouldn't do &lt;em&gt;something&lt;/em&gt;, you know?&lt;/p&gt;
&lt;p&gt;So today I will explain how I made a super simple URL shortening service for myself and hopefully it will help some of you.&lt;/p&gt;
&lt;p&gt;The code is available &lt;a href="/url-shortener"&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Please note:&lt;/strong&gt; This is &lt;em&gt;my&lt;/em&gt; take on a URL shortener and this whole thing is written as an excercise based on my current level of PHP knowledge, so I may revisit this in the future. This is most likely not the best or most effecient way of doing this. Please keep this in mind while reading this and, of course, I'd love to hear from you if you've got any ideas or suggestions.&lt;/p&gt;
&lt;h2 id="why-do-iyou-need-this"&gt;Why do I/you need this?&lt;a class="headerlink" href="#why-do-iyou-need-this" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Traditionally, I guess, URL shorteners were and are used to make long URLs short. These are often used in places where there exists a limit on the character count that can be used such as Twitter, SMS, Mastodon, various descriptions et cetera.
They can also be used to create "nice" links (i.e. &lt;code&gt;service.tld/mylink&lt;/code&gt; is "nicer" than &lt;code&gt;somewebsiteonline.tld/service/longlinkgalore?query=yesplease&lt;/code&gt;, right?) and as a way to make sure certain links don't change (e.g. &lt;code&gt;service.tld/blog&lt;/code&gt; will always point to your blog's address even if you move to a different domain).&lt;/p&gt;
&lt;h2 id="prerequisites"&gt;Prerequisites&lt;a class="headerlink" href="#prerequisites" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I am personally using nginx with a directive that forwards all requests to the index file in case the requested path is not found.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class="language-CONF"&gt;location / {
try_files $uri $uri/ /index.php$is_args$args;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;There is no need for a database as all entries as stored in a file.&lt;/li&gt;
&lt;li&gt;Currently, I am using &lt;a href="https://insomnia.rest/"&gt;Insomnia&lt;/a&gt; to add, remove and list entries. There is no GUI.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-database"&gt;The "database"&lt;a class="headerlink" href="#the-database" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Instead of using an SQL database that would've indubitably made this more complex than it should be (not by much, but still) we are going to store all entries in a simple file.&lt;/p&gt;
&lt;p&gt;To introduce some security, I went with a PHP file that has the following header:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;&amp;lt;?php header(&amp;quot;HTTP/1.0 404 Not Found&amp;quot;); die(); ?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means, that if the database file is accessed directly it will just return a 404 error.
The entries themselves are stored on an entry per line basis with a single space separator between the key and URL, e.g.:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@home https://0xff.nu
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="the-script"&gt;The script&lt;a class="headerlink" href="#the-script" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The script needs to have a couple of parts in order to work as we want it to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Variables and Init - Where we store and create the things.&lt;/li&gt;
&lt;li&gt;Database - Reading from and storing to the database file.&lt;/li&gt;
&lt;li&gt;Router - Routing the request through the correct method.&lt;/li&gt;
&lt;li&gt;Redirection - The main purpose of this thing - redirecting the request.&lt;/li&gt;
&lt;li&gt;Management - Creating and deleting entries.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="variables-and-init"&gt;Variables and Init&lt;a class="headerlink" href="#variables-and-init" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We are using a handful of variables:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;private $filename, $database, $prefix;
private $dbHeader = '&amp;lt;?php header(&amp;quot;HTTP/1.0 404 Not Found&amp;quot;);die(); ?&amp;gt;'.PHP_EOL;
private $authkey = '79A69C0D4B9DFCD94B1BF72799E334D0CC4D1972';

public function __construct(string $filename, string $prefix)
{
    $this-&amp;gt;filename = $filename;
    $this-&amp;gt;prefix = $prefix;
    $this-&amp;gt;readDatabase();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$filename&lt;/code&gt; - The database filename we initialize the class with.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$database&lt;/code&gt; - This is where the database will be stored after it's parsed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$prefix&lt;/code&gt; - Entry prefix, if specified. I am using &lt;code&gt;@&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$dbHeader&lt;/code&gt; - The header that should be prepended to the database file.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$authkey&lt;/code&gt; - Hashed key that should be used to authenticate management commands.&lt;/li&gt;
&lt;li&gt;The contructor method sets the variables with the values given once the class is instantiated.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="database"&gt;Database&lt;a class="headerlink" href="#database" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;private function initializeDatabase()
{
    return file_put_contents($this-&amp;gt;filename, $this-&amp;gt;dbHeader);
}

private function readDatabase()
{
    $this-&amp;gt;database = [];
    if (!file_exists($this-&amp;gt;filename)) {
        $this-&amp;gt;initializeDatabase();
    }
    $rawDatabase = array_slice(file($this-&amp;gt;filename), 1);
    foreach ($rawDatabase as $entry) {
        $entry = explode(' ', $entry);
        $this-&amp;gt;database[$entry[0]] = trim($entry[1]);
    }
}

private function updateDatabase()
{
    $fh = fopen($this-&amp;gt;filename, 'w');
    fwrite($fh, $this-&amp;gt;dbHeader);
    foreach ($this-&amp;gt;database as $key =&amp;gt; $url) {
        fwrite($fh, &amp;quot;{$key} {$url}&amp;quot; . PHP_EOL);
    }
    fclose($fh);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;initializeDatabase()&lt;/code&gt; creates a new file and appends the header to it.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readDatabase()&lt;/code&gt; reads the database (or calls to initialize it), parses the entries and stores them into the &lt;code&gt;$database&lt;/code&gt; variable. The first "entry" is sliced off as it's actually the header (&lt;code&gt;$dbHeader&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;updateDatabase()&lt;/code&gt; updates the database &lt;code&gt;$filename&lt;/code&gt; with the values from &lt;code&gt;$database&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="router"&gt;Router&lt;a class="headerlink" href="#router" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;private function parseRequest()
{
    $request['request'] = trim($_SERVER['REQUEST_URI'], '/');
    $request['query'] = $_POST;
    if (isset($request['query']['key'])) {
        $request['query']['key'] = $this-&amp;gt;prefix.$request['query']['key'];
    }
    return $request;
}

public function matchRequest() {
    $request = $this-&amp;gt;parseRequest();
    $command = str_replace('@','',$request['request']).'Entry';
    if (is_callable([$this, $command]) &amp;amp;&amp;amp; $this-&amp;gt;validate()) {
        call_user_func_array([$this, $command], [$request['query']]);
    } else {
        $this-&amp;gt;doRedirect($request['request']);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;parseRequest()&lt;/code&gt; parses the request that was made from both the URI and POST data.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;matchRequest()&lt;/code&gt; routes the request through the appropriate method, else we're calling the &lt;code&gt;doRedirect()&lt;/code&gt; method to try and perform the redirect.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note the &lt;code&gt;validate()&lt;/code&gt; method. We use this to make sure the request is authorized:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;private function isAuthenticated()
{
    return isset($_SERVER['PHP_AUTH_PW']) &amp;amp;&amp;amp; $this-&amp;gt;authkey === $_SERVER['PHP_AUTH_PW'];
}

private function validate()
{
    if (!$this-&amp;gt;isAuthenticated()) {
        http_response_code(401);
        die();
    }
    return true;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the auth key does not match, halt execution and return &lt;code&gt;401 Unauthorized&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I am using a &lt;a href="https://en.wikipedia.org/wiki/Basic_access_authentication"&gt;basic auth&lt;/a&gt; so it's important to use this together with HTTPS to actually be somewhat secure.
You can, of course, implement better security if you wish.&lt;/p&gt;
&lt;h3 id="redirection"&gt;Redirection&lt;a class="headerlink" href="#redirection" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Redirection is very, very simple:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;private function doRedirect(string $key)
{
    if ($this-&amp;gt;doesEntryExist($key)) {
        header(&amp;quot;Location: {$this-&amp;gt;database[$key]}&amp;quot;, true, 301);
    } else {
        http_response_code(404);
        die();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the requested key exists in the database, we simply append a &lt;code&gt;Location&lt;/code&gt; header&lt;sup id="fnref:2-1"&gt;&lt;a class="footnote-ref" href="#fn:2-1"&gt;1&lt;/a&gt;&lt;/sup&gt; which redirects to the location we want.
If it doesn't, we return a &lt;code&gt;404 Not Found&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="management"&gt;Management&lt;a class="headerlink" href="#management" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For management, we have four methods: add, update, remove and list entries:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;private function addEntry(array $entry)
{
    $entry['key'] = $entry['key'] ?? $this-&amp;gt;generateID();
    $this-&amp;gt;database[$entry['key']] = $entry['loc'];
    $this-&amp;gt;updateDatabase($this-&amp;gt;database);
}

private function updateEntry(array $entry)
{
    if ($this-&amp;gt;doesEntryExist($entry['key'])) {
        $this-&amp;gt;database[$entry['key']] = $entry['loc'];
        $this-&amp;gt;updateDatabase($this-&amp;gt;database);
    }
}

private function removeEntry(array $entry)
{
    if ($this-&amp;gt;doesEntryExist($entry['key'])) {
        unset($this-&amp;gt;database[$entry['key']]);
        $this-&amp;gt;updateDatabase($this-&amp;gt;database);
    }
}

private function listEntry()
{
    $this-&amp;gt;response($this-&amp;gt;database);
}

private function generateID(int $length = 3)
{
    $id = str_shuffle(base64_encode(microtime()));
    return $this-&amp;gt;prefix.substr($id, 0, $length);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These are fairly self-explanatory. Each method does the neccessary change and updates the database.
You can also notice that we can create new entries without specifying a key.&lt;/p&gt;
&lt;p&gt;If a key is not specified, it will be created by &lt;code&gt;generateID()&lt;/code&gt; which, in essence, creates an ID of a specified &lt;code&gt;$length&lt;/code&gt; from a randomized, base64 encoded unix timestamp.
You may notice there's no verification if the generated ID already exists, but this should be easy to add using &lt;code&gt;doesEntryExist()&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;a class="headerlink" href="#conclusion" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This was fairly easy but still a fun to write excercise. I am certain some things can be further simplified or written better to begin with, so I will revisit this little project from time to time to make some adjustments.&lt;/p&gt;
&lt;p&gt;This functionality will probably be added to &lt;a href="/saisho"&gt;Saisho&lt;/a&gt; or may be on a separate domain, we'll see.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:2-1"&gt;
&lt;p&gt;Location header: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location"&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><pubDate>Thu, 08 Oct 2020 00:00:00 -0000</pubDate></item><item><title>Picoblog</title><link>https://0xff.nu/picoblog/</link><description>&lt;p&gt;I wrote briefly (or not so briefly) &lt;a href="https://0xff.nu/microblogging"&gt;about microblogging&lt;/a&gt; just recently and while the microblog code will probably be added to Saisho, I've decided to also make it available as standalone as I realize not everyone might be using Saisho.&lt;/p&gt;
&lt;p&gt;Picoblog is very very simple but it gets the job done.&lt;/p&gt;
&lt;p&gt;Creating a microblog page is super simple:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;include_once 'picoblog.php';
$mb = new \hxii\PicoBlog('blog.txt');
echo $mb-&amp;gt;renderEntries($mb-&amp;gt;getEntries('all'));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This being said, please take a look at &lt;a href="https://git.sr.ht/~hxii/picoblog/tree/master/blog.php"&gt;&lt;code&gt;blog.php&lt;/code&gt;&lt;/a&gt; for a more complete usage example.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://0xff.nu/microblog"&gt;Demo (in Saisho)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://git.sr.ht/~hxii/picoblog"&gt;Download from Sourcehut&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/hxii/picoblog"&gt;Download from GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://todo.sr.ht/~hxii/picoblog"&gt;Bugs&lt;/a&gt;&lt;/p&gt;</description><pubDate>Fri, 02 Oct 2020 00:00:00 -0000</pubDate></item><item><title>A case for microblogging</title><link>https://0xff.nu/microblogging/</link><description>&lt;blockquote&gt;
&lt;p&gt;This entry is just me thinking out loud and trying to make a case for microblogging.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Recently I &lt;a href="https://merveilles.town/@hxii/104875101804537409"&gt;tooted&lt;/a&gt; about potentially adding support for microblogging to, at least, my website if not Saisho in general. But this made me think and consider the options, requirements, and ways of implementing this (potentially) minor functionality.&lt;/p&gt;
&lt;p&gt;The basic need and idea are simple - a way to distinguish between long-form articles and posts to short updates, shares, and misc posts, but it turns out that implementing this correctly could prove a little bit more challenging than I initially thought.&lt;/p&gt;
&lt;p&gt;There are several problems that must be addressed and questions that must be answered:
1. Necessity - Do I really need to add this functionality? Why not just mix all the different kinds of posts together? Is this going to make my life easier?
2. File Structure - If I do implement this, would the microblog entries be in the same &lt;code&gt;/data/&lt;/code&gt; folder? A separate folder? How would the files look like? Metadata?
3. Visuals - How would I display the microblog entries? Should they be in a separate list? Should I emphasize the distinction?&lt;/p&gt;
&lt;h2 id="necessity"&gt;Necessity&lt;a class="headerlink" href="#necessity" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To be frank here, I'm not &lt;em&gt;entirely&lt;/em&gt; sure I &lt;em&gt;need&lt;/em&gt; microblogging, but I do know that I will sometimes refrain from posting something unless I have enough "material", so microblogging would certainly address this.&lt;/p&gt;
&lt;p&gt;I guess it is also important to understand what microblogging is in its essence and to the best of my understanding it exists to express thoughts out loudly, draft things and quickly share resources with the people that are following your blog. A replacement for Twitter, if you will.&lt;/p&gt;
&lt;p&gt;Maybe for this reason the micro-entries should be separated from, you know, the "actual content".&lt;/p&gt;
&lt;h2 id="file-structure"&gt;File Structure&lt;a class="headerlink" href="#file-structure" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are two issues here:
- Entries require a front matter header. The whole point of microblogging is for it to be a quick way to share information, so writing metadata doesn't make sense.
- All entries are stored in the &lt;code&gt;/data&lt;/code&gt; folder. It would make sense to keep all entries in the same folder, but it would also make sense to separate the micro-entries from the rest of the content, in the interest of keeping some sort of organization.&lt;/p&gt;
&lt;p&gt;Both of these would most likely necessitate a code change in Saisho, at the very least the separate data folder part.
The header conundrum can be resolved by using an API that will create the files with the appropriate metadata - which will make creating entries even simpler.&lt;/p&gt;
&lt;p&gt;There are a few ways to go about this:
1. Separate data folder but metadata stays - core code change which means everyone gets microblogging. Will probably require API to create micro-entries.
2. Separate data folder and no metadata - core code changes with an extra side of code changes, as metadata will be taken from filename and fileinfo.
3. Same data folder and metadata stays - no core changes. Doable by using a "magic" tag and the implementation relies on the template.
4. Same data folder and no metadata - requires core changes (same as #2), but implementation is the same as above.&lt;/p&gt;
&lt;h2 id="visuals"&gt;Visuals&lt;a class="headerlink" href="#visuals" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I do believe it's obvious that micro-entries have to be separate from the rest of the content in one way or another, as having them mixed with the other content will either
A. Create visual clutter.
B. Make articles hard to find with the number of micro-entries or
C. All of the above.&lt;/p&gt;
&lt;p&gt;Think of this as a "blog" vs. "professional content" or similar terms.&lt;/p&gt;
&lt;p&gt;Since we know a distinction HAS to be made, the question then is what is the best way to do it. Is it a separate page? A list similar to the article list? If so, should it be on the same page? If not, should I only display the latest entry? All entries? N entries?&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;This is the part I'm struggling with.&lt;/mark&gt; I will be exploring different methods and update this article accordingly.&lt;/p&gt;
&lt;h2 id="lets-discuss"&gt;Let's Discuss&lt;a class="headerlink" href="#lets-discuss" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What do you think about microblogging? Do you or would you utilize something like microblogging?&lt;/p&gt;
&lt;p&gt;If so, what do you think is the best way to do it correctly?&lt;/p&gt;
&lt;h1 id="the-chosen-path"&gt;The Chosen Path&lt;a class="headerlink" href="#the-chosen-path" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;After writing the article above, I continued thinking, testing different things, and working on implementing the microblogging functionality given the constraints and requirements that I have from the microblogging functionality into Saisho.&lt;/p&gt;
&lt;h2 id="source-file"&gt;Source File&lt;a class="headerlink" href="#source-file" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I wanted to make sure the source file is humanly readable even when looking at it directly, so I've decided on using a plain TXT file in reversed order (latest entry is always at the top) that follows a very simple format:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{RFC3339 Date}  {Unique ID} {Flags} {Entry text with MarkDown}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A sample entry would look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;2020-09-26T21:17:34Z    ed58b9 P Aside from the ID and the flags (still need to figure out if I *really* need those), the format is TWTXT compatible.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, the format is &lt;a href="https://twtxt.readthedocs.io/en/latest/user/twtxtfile.html#format-specification"&gt;twtxt&lt;/a&gt; compatible (aside from the ID and flags).&lt;/p&gt;
&lt;p&gt;Flags are TBD as I've added them thinking I'll find use (for example P for Published, S for Secret, etc.) for them, but I'm not entirely sure yet.&lt;/p&gt;
&lt;h2 id="presentation"&gt;Presentation&lt;a class="headerlink" href="#presentation" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I've decided to have an entirely separate page for the microblog to make sure people can actually get to it (the other option is having it below the main article list).&lt;/p&gt;
&lt;p&gt;A new 'special' page was made in Saisho to make this happen:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;case 'microblog':
    include_once INC_DIR.DS.'microblog.php';
    $mb = new microblog('blog.txt');
    $entries = (isset($requestedPage['query']['id'])) ? $mb-&amp;gt;getEntries($requestedPage['query']['id']) : $mb-&amp;gt;getEntries('all');
    $content = (object)[
        'title' =&amp;gt; 'Microblog',
        'body' =&amp;gt; $mb-&amp;gt;renderEntries($entries),
    ];
    $page = (object)['type'=&amp;gt;'microblog', 'content'=&amp;gt;$content];
break;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This made me realize that creating 'special' pages in Saisho is less than comfortable, but this will be addressed at a later time.&lt;/p&gt;
&lt;p&gt;As you can see, I've made it so that you can link to specific entries in the microblog by using &lt;code&gt;/microblog?id={id-of-entry}&lt;/code&gt; or if you navigate to &lt;a href="/microblog"&gt;/microblog&lt;/a&gt; without an ID, you'll get all the entries.&lt;/p&gt;
&lt;p&gt;The microblog is using &lt;a href="https://gist.github.com/jbroadway/2836900"&gt;Slimdown&lt;/a&gt; as opposed to Parsedown which is a very simple and quick Markdown parser with a very limited subset of tags.&lt;/p&gt;
&lt;p&gt;The output on the microblog page is a simple ID (which gives you the date when you hover above it) and the parsed entry text.&lt;/p&gt;
&lt;h2 id="posting"&gt;Posting&lt;a class="headerlink" href="#posting" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Currently, adding new entries to the microblog can be done either by adding them directly to the source file (less than ideal since you need both the timestamp and ID) or by using a simple API.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Posting an entry via API" src="https://0xff.nu/i/O5AitXEKej-fs8.png" title="Posting an entry via API" /&gt;&lt;/p&gt;
&lt;p&gt;The API currently only supports creating new entries, but I might modify it to support changing and removing entries as well.&lt;/p&gt;
&lt;h2 id="closing-words"&gt;Closing Words&lt;a class="headerlink" href="#closing-words" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is still a learning experience for me and things may change depending on my requirements from this functionality. That being said, I am trying to keep it (and everything else in Saisho) simple and functional in a way that I will use it.&lt;/p&gt;
&lt;p&gt;The format might still change depending on if I can find a use for flags and I still need to revise and refine the API.&lt;/p&gt;
&lt;p&gt;The code will be pushed to both Sourcehut and GitHub once I verify that everything is working as it should.&lt;/p&gt;
&lt;p&gt;Got any ideas? Want to discuss this? Fill out the form below and don't forget to mention your e-mail address.&lt;/p&gt;</description><pubDate>Mon, 21 Sep 2020 00:00:00 -0000</pubDate></item><item><title>Image Optimization for The Web</title><link>https://0xff.nu/image-optimization/</link><description>&lt;p&gt;In my &lt;a href="https://0xff.nu/speed-pt3#images"&gt;previous rant about web bloat&lt;/a&gt; I briefly spoke about image sizes and incorrect image usage and what you can do to either reduce it or make your visitors' life easier.
A &lt;a href="https://merveilles.town/@FredBednarski/104821640863683259"&gt;specific toot&lt;/a&gt; prompted me to continue and expand about this with the hopes that this information will help some of you.&lt;/p&gt;
&lt;h2 id="tldr"&gt;TL;DR&lt;a class="headerlink" href="#tldr" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Images, like anything else, are to be use to answer a need or solve a problem&lt;sup id="fnref:2-1"&gt;&lt;a class="footnote-ref" href="#fn:2-1"&gt;1&lt;/a&gt;&lt;/sup&gt; (like demonstrating something in a visual manner).&lt;/p&gt;
&lt;p&gt;If you don't absolutely need images - don't use them. If you &lt;em&gt;have&lt;/em&gt; to use images, make sure they are optimized.&lt;/p&gt;
&lt;h2 id="image-formats"&gt;Image Formats&lt;a class="headerlink" href="#image-formats" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Many things have been said about image formats and I will most likely have nothing new to contribute, so instead I'll direct you to some useful reading material:
- &lt;a href="https://css-tricks.com/using-webp-images/"&gt;Using WebP Images&lt;/a&gt;
- &lt;a href="https://abraia.me/docs/image-optimization/"&gt;How to optimize images for web&lt;/a&gt;
- &lt;a href="https://www.freecodecamp.org/news/best-image-format-for-web-in-2019-jpeg-webp-heic-avif-41ba0c1b2789/"&gt;Picture this: the best image format for the web in 2019&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="image-size"&gt;Image Size&lt;a class="headerlink" href="#image-size" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before I delve into fancy (and helpful) tricks that you can do to make sure your page load speeds are not inhibited by images, it is important to deal with the root of the problem - image size.&lt;/p&gt;
&lt;p&gt;As I mentioned in my previous rant (linked above), I often see websites usings images of disproportional sizes (both image dimension and filesize) to their intended purpose where people would, for example, use a large (1728x1152) profile photo and resize it via CSS (to 30%, effectively 496x331 on a 1080P display):
&lt;img alt="Very large profile photo" src="https://0xff.nu/i/Quarrelsome-e8b8d9b085ba00e3.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;I'm not going to rant (again) why you really (really) shouldn't do this, so we'll get straight to it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Optimize.&lt;/strong&gt; Optimize your images. Deal with the dimensions first - if you know you're only going to use 30% of your image, resize it beforehand!
Using smaller dimensions will also result in smaller filesizes.&lt;/p&gt;
&lt;p&gt;You think larger screens deserve larger images (not of your fucking face, please!)? Save multiple sizes and use &lt;a href="https://html.com/attributes/img-srcset/"&gt;&lt;code&gt;srcset&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You made your images smaller? Thank you! You want to go the extra mile? Use optimization tools, either online or offile. For example:&lt;/p&gt;
&lt;h3 id="online-tools"&gt;Online Tools&lt;a class="headerlink" href="#online-tools" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tinypng.com/"&gt;tinypng&lt;/a&gt; and &lt;a href="https://tinyjpg.com/"&gt;tinyjpg&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://compressor.io/"&gt;compressor.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ditherit.com/"&gt;Dither it!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.jpeg.io/"&gt;jpeg.io&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="offline-tools"&gt;Offline Tools&lt;a class="headerlink" href="#offline-tools" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://x128.ho.ua/color-quantizer.html"&gt;Color Quantizer (WIN)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://imageoptim.com/mac"&gt;ImageOptim (MAC)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pngquant.org/#download"&gt;pngquant (Multi)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pmt.sourceforge.io/pngcrush/"&gt;pngcrush (NIX/WIN)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Kilian/Trimage"&gt;trimage (NIX/MAC)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;small&gt;Know any other good tools? LMK.&lt;/small&gt;&lt;/p&gt;
&lt;h2 id="lazy-loading"&gt;Lazy Loading&lt;a class="headerlink" href="#lazy-loading" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Unless images are part of the layout, you should always be using lazy loading.&lt;/p&gt;
&lt;p&gt;Lazy loading will make the page load faster, as images that are offscreen will not be loaded until they are scrolled into view.&lt;/p&gt;
&lt;p&gt;All you have to do is add &lt;code&gt;loading="lazy"&lt;/code&gt; as an attribute to your &lt;code&gt;img&lt;/code&gt; tags, e.g.:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;img src="path-to-img.jpg" alt="Image description" loading="lazy"&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You can read more on CSS-Tricks about &lt;a href="https://css-tricks.com/native-lazy-loading/"&gt;Native Lazy Loading&lt;/a&gt; and &lt;a href="https://css-tricks.com/the-complete-guide-to-lazy-loading-images/"&gt;The Complete Guide to Lazy Loading Images&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="going-the-extra-step"&gt;Going the extra step&lt;a class="headerlink" href="#going-the-extra-step" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Your images have been smallified and are lazy, but you want to do a bit more, huh?
Another thing you can do is make sure images are only loading once a user triggers them.&lt;/p&gt;
&lt;h3 id="the-js-route"&gt;The JS route&lt;a class="headerlink" href="#the-js-route" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is a technique I employ here, on &lt;a href="https://0xff.nu"&gt;my website&lt;/a&gt;, and it consists of setting a placeholder as the image source and the actual image under a &lt;code&gt;data-src&lt;/code&gt; attribute, creating a listener and switching the sources once the user clicks on the image.&lt;/p&gt;
&lt;p&gt;Image example:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;img src="/load.png" data-src="https://0xff.nu/i/Tubby-ae0ddc24569cabab.png" alt="Holy fucking unreadable font, Batman!" loading="lazy"&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The JS code:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-JavaScript"&gt;  &amp;lt;script type=&amp;quot;text/javascript&amp;quot; defer&amp;gt;
  const images = document.querySelectorAll(&amp;quot;img[data-src]&amp;quot;);
  images.forEach(function(image) {
      image.addEventListener('click', e =&amp;gt; {
          e.target.src = e.target.dataset.src;
          image.removeEventListener('click', e);
      });
  });
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="the-css-route"&gt;The CSS route&lt;a class="headerlink" href="#the-css-route" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you don't want to use JavaScript (I wouldn't blame you), you can achieve a similar effect using HTML and CSS. You can see a little demo I wrote on &lt;a href="https://codepen.io/nocte/pen/wvGpOyE"&gt;Codepen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The gist is to place the image offscreen or hide it using a CSS rule and use a checkbox element to switch the styling once it's checked.&lt;/p&gt;
&lt;p&gt;For example, the HTML:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-HTML"&gt;&amp;lt;div class=&amp;quot;fig&amp;quot;&amp;gt;
  &amp;lt;input type=&amp;quot;checkbox&amp;quot; id=&amp;quot;loadimage&amp;quot; name=&amp;quot;loadimage&amp;quot;&amp;gt;
  &amp;lt;label for=&amp;quot;loadimage&amp;quot;&amp;gt;Load Image&amp;lt;/label&amp;gt;
  &amp;lt;img src=&amp;quot;https://images.unsplash.com/photo-1568431477192-52bb13a55088&amp;quot; loading=&amp;quot;lazy&amp;quot; alt=&amp;quot;A cute hedgehog&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the CSS:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-CSS"&gt;.fig {
  display: inline
}

.fig label {
  color: blue;
  cursor: pointer;
  text-decoration: underline;
}

.fig input {
  display: none
}

.fig img {
  position: absolute;
  left: -9999px;
  display: none;
}

.fig input:checked ~ img {
  position: relative;
  left: 0;
  display: block;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This might be a bit less straightforward and more cumbersome solution, but it works.&lt;/p&gt;
&lt;h3 id="in-conclusion"&gt;In conclusion&lt;a class="headerlink" href="#in-conclusion" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You don't have to do this, and you might argue how this is kind of fucking annoying in terms of UX, especially if you are using a lot of images, and you'd be right and this is exactly where you need to excercise common sense.&lt;/p&gt;
&lt;h2 id="closing-words"&gt;Closing words&lt;a class="headerlink" href="#closing-words" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Images are only part of the web bloat, but they could be one of the easier things to fix. Everything depends on you and how much effort and thought you're willing to put into this.&lt;/p&gt;
&lt;p&gt;The important thing is that we acknowledge the problem and take steps towards fixing it, rather than contributing to it.&lt;/p&gt;
&lt;p&gt;Let's make the fucking 
web nice again, shall we?&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:2-1"&gt;
&lt;p&gt;Part of my, I guess, way of minimalism, is that when writing code, if something doesn't solve a problem, answer a need or makes someone's life easier it's most likely not required. This is true for many things, images included. I only reserve images for things I cannot show using text.&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><pubDate>Tue, 08 Sep 2020 00:00:00 -0000</pubDate></item><item><title>Links</title><link>https://0xff.nu/links/</link><description>&lt;p&gt;I try and find inspiration in everything, hence compiling a list of links that I find inspiration in or use on a constant (or not) basis is not an easy task (for me).&lt;/p&gt;
&lt;p&gt;That said, here are some of my sources:&lt;/p&gt;
&lt;h3 id="interesting-reads"&gt;Interesting Reads&lt;a class="headerlink" href="#interesting-reads" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://solar.lowtechmagazine.com/"&gt;Low Tech Magazine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://n-o-d-e.net/index.html"&gt;NODE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;People on the &lt;a href="https://webring.xxiivv.com/"&gt;Webring&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://css-tricks.com/"&gt;CSS-Tricks&lt;/a&gt;, unsurprisingly.&lt;/li&gt;
&lt;li&gt;Lobste.rs on &lt;a href="https://lobste.rs/t/design"&gt;design&lt;/a&gt;, &lt;a href="https://lobste.rs/t/web"&gt;web&lt;/a&gt; and &lt;a href="https://lobste.rs/t/php"&gt;php&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="the-light-web"&gt;The light web&lt;a class="headerlink" href="#the-light-web" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://portable.fyi/"&gt;Portable thoughts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://neat.joeldare.com/"&gt;Neat CSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://every.sdf.org/"&gt;every.sdf.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mataroa.blog/"&gt;Mataroa&lt;/a&gt; and &lt;a href="https://bearblog.dev/"&gt;Bear.blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://txti.es/"&gt;txti&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiby.me/"&gt;Wiby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://uglyduck.ca/"&gt;Ugly Duck&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://seirdy.one/2020/11/23/website-best-practices.html"&gt;An opinionated list of best practices for textual websites&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://1mb.club/"&gt;1MB Club&lt;/a&gt;, &lt;a href="https://512kb.club/"&gt;512kb Club&lt;/a&gt;, &lt;a href="https://250kb.club/"&gt;250kb Club&lt;/a&gt;, &lt;a href="https://10kbclub.com/"&gt;10kb Club&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="inspiration-for-this-website"&gt;Inspiration for this website&lt;a class="headerlink" href="#inspiration-for-this-website" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://hex22.org/"&gt;Hunor Karamán&lt;/a&gt;, &lt;a href="https://avanier.now.sh/"&gt;Avanier&lt;/a&gt;, &lt;a href="https://tom.so/"&gt;Tom Hackshaw&lt;/a&gt;, the different &lt;a href="/motherfucking-websites"&gt;Motherfucking Websites&lt;/a&gt; et al.&lt;/p&gt;</description><pubDate>Mon, 31 Aug 2020 00:00:00 -0000</pubDate></item><item><title>Saisho Update 20200830 &amp;#x1F51C;</title><link>https://0xff.nu/saisho20200830/</link><description>&lt;p&gt;I don't write nearly as enough as I should, so I've decided that I'm going to share any progress updates and what went into making them of some of my publicly available projects, like &lt;a href="https://paulglushak.com/saisho"&gt;Saisho&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Besides general code fixes and improvements, this update is a low-key code refactor that I just &lt;em&gt;had&lt;/em&gt; to do.&lt;/p&gt;
&lt;p&gt;I'm always looking for ways to improve the code of Saisho keeping in mind simplicity and speed (both server and client side) over adding new features. The whole point of Saisho is to have a semi-static website that doesn't add much overhead over serving pure HTML.&lt;/p&gt;
&lt;h2 id="templates"&gt;Templates&lt;a class="headerlink" href="#templates" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the things new to this update is that the visual side is now separate from the logic side. Despite me wanting to keep Saisho simple and contained in one file, the template side of it made the code a bit messy so out it goes.&lt;/p&gt;
&lt;p&gt;It is, perhaps, a very crude implementation of a "templating system" (again, due to me wanting to keep the code as simple and as fast as possible), but it will allow anyone that uses Saisho a simpler way to customize it to their liking.&lt;/p&gt;
&lt;p&gt;The core of the "system" is loading a template from &lt;code&gt;TEMPLATE_DIR&lt;/code&gt; with the corresponding page type, e.g. &lt;code&gt;page&lt;/code&gt;, &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;notfound&lt;/code&gt; etc:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;// Called like so:
$page = (object)['type' =&amp;gt; 'page', 'content' =&amp;gt; $this-&amp;gt;renderPage($pagePath) ];
$this-&amp;gt;renderTemplate($page-&amp;gt;type, [$page-&amp;gt;content]);

private function renderTemplate(string $template, array $args)
{
    ob_start();
    if (!file_exists(TEMPLATE_DIR.DS.$template.'.php')) return (string) &amp;quot;Template $template.php not found!&amp;quot;;
    // ...
    include TEMPLATE_DIR.DS.$template.'.php';
    return ob_get_clean();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The only HTML left in the main file is in &lt;code&gt;renderPageList(array $list, $filter)&lt;/code&gt; as I think this is a core function, but I may just move it to the template and leave a function that outputs an array to be used.&lt;/p&gt;
&lt;h2 id="caching"&gt;Caching&lt;a class="headerlink" href="#caching" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the things I've noticed during the implementation/split of the template code was that I've made a stupid mistake that caused the page you're looking at to be rendered even if a valid, cached page was available.&lt;/p&gt;
&lt;p&gt;This happened because the request handler (&lt;code&gt;handleRequest(string $requestedPage)&lt;/code&gt;) was executing &lt;code&gt;$this-&amp;gt;renderPage($pagePath)&lt;/code&gt;&lt;sup id="fnref:2-1"&gt;&lt;a class="footnote-ref" href="#fn:2-1"&gt;1&lt;/a&gt;&lt;/sup&gt; for the content as part of it's output (which was creating a page object with type and content).&lt;/p&gt;
&lt;p&gt;The solution was to modify &lt;code&gt;handleRequest()&lt;/code&gt; so that it checks for cache first and only then creates the page object:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;$cachePath = CACHE_DIR . DS . $requestedPage . '.html';
if (!$this-&amp;gt;tryCache($cachePath)) {
    $page = (object)['type' =&amp;gt; 'page', 'content' =&amp;gt; $this-&amp;gt;renderPage($pagePath) ];
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;tryCache()&lt;/code&gt; would return &lt;code&gt;false&lt;/code&gt; if the cached page is either invalid or not available, or, in the case that cache is valid and available just return the page and exit.&lt;/p&gt;
&lt;p&gt;This resulted in cached page loading time going down from about ~2.145ms to ~0.127ms. You might say this is yak shaving, and you'd be right, but even being a &lt;a href="https://www.joelonsoftware.com/2009/09/23/the-duct-tape-programmer/"&gt;duct tape programmer&lt;/a&gt; has it's limits and I want to do this thing properly so that I can also learn a thing or two myself.&lt;/p&gt;
&lt;h2 id="tags"&gt;Tags&lt;a class="headerlink" href="#tags" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I honestly don't use tags much (I probably should), but this was a good way to use "internal tags" like "hide" and "now" which will omit pages from the list:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;define('TAGS_TO_HIDE', ['hide', 'now']);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These tags are filtered using &lt;code&gt;array_filter&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;return (array)array_filter($parsedPages, function ($item) use ($filter) {
    if ($filter === true) {
        return !array_intersect(TAGS_TO_HIDE, $item-&amp;gt;tags);
    } elseif (is_string($filter)) {
        return in_array($filter, $item-&amp;gt;tags);
    } else {
        return 1;
    }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This allows you to pass &lt;code&gt;true&lt;/code&gt; to filter out the hidden tags, or a &lt;code&gt;string&lt;/code&gt; to filter by tag.&lt;/p&gt;
&lt;h2 id="speed"&gt;Speed&lt;a class="headerlink" href="#speed" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In order to make pages load even quicker, I made the decision to replace all images with a placeholder which will load the original image once clicked.&lt;/p&gt;
&lt;p&gt;As I'm not smart enough (also, please keep in mind this is a personal project), the change was done directly in Parsedown's code:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;'attributes' =&amp;gt; array(
    'src' =&amp;gt; '/load.png',
    'data-src' =&amp;gt; $Link['element']['attributes']['href'],
    'alt' =&amp;gt; $Link['element']['handler']['argument'],
    'loading' =&amp;gt; 'lazy',
),
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The placeholder image itself is 256 bytes.
The switch, once the placeholder is clicked is done in vanilla JS:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-JavaScript"&gt;const images = document.querySelectorAll(&amp;quot;img[data-src]&amp;quot;);
images.forEach(function(image) {
    image.addEventListener('click', e =&amp;gt; {
        e.target.src = e.target.dataset.src;
        image.removeEventListener('click', e);
    });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="other-things"&gt;Other things&lt;a class="headerlink" href="#other-things" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Added external link styling to help distinguish between internal and external links. Figured a simple "\219D" () will suffice.&lt;/li&gt;
&lt;li&gt;Added &lt;code&gt;modified&lt;/code&gt; key to page objects.&lt;/li&gt;
&lt;li&gt;Want to make a specific item stand out in the list? Use the &lt;code&gt;style&lt;/code&gt; property in the page header to add custom CSS.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="whats-next"&gt;What's next?&lt;a class="headerlink" href="#whats-next" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I'd like to refactor &lt;code&gt;handleRequest()&lt;/code&gt; to make it easier to add custom paths, as, for example, to add a projects list requires me to do the following:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;case 'projects':
    $list = $this-&amp;gt;listPages();
    $page = (object)['type'=&amp;gt;'list', 'content'=&amp;gt;$this-&amp;gt;renderPageList($list, 'project')];
break;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can see how this might not be the best or easiest way.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:2-1"&gt;
&lt;p&gt;&lt;a href="https://git.sr.ht/~hxii/saisho/tree/master/index.php#L33"&gt;https://git.sr.ht/~hxii/saisho/tree/master/index.php#L33&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><pubDate>Sun, 30 Aug 2020 00:00:00 -0000</pubDate></item><item><title>Pursuing Speed, Pt. 3</title><link>https://0xff.nu/speed-pt3/</link><description>&lt;blockquote&gt;
&lt;p&gt;This entry (and collection of links) is a continuation of &lt;a href="https://0xff.nu/speed-pt2"&gt;Pursuing Speed, Pt. 2&lt;/a&gt; which you can read for context.&lt;/p&gt;
&lt;p&gt;You are more than welcome to share the link to this with your friends and colleagues.
If you'd like to contribute relevant points of interesting links or resources, please contact me using the form at the bottom of the page.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;At this point, you might be going "This dude can only rant! Provide some alternatives, then!" and, in a sense, you'd have a point, since all I did so far is rant and only briefly talk (or rather mention) the "correct" way to go about things.&lt;/p&gt;
&lt;p&gt;So it's time to remedy this. In this post, I will try to provide tips and rough guidelines as well as links to further reading which will help you in making your website faster and more accessible.&lt;/p&gt;
&lt;p&gt;As I've said before, speed, lightness, mindfullness and minimalism do not neccessarily mean that your website must or will look as minimal (and some would say barren) as mine, not at all! You can have colors, images and whatever fucking flashy, hip things you want, but you MUST be mindful with everything that you add. Dont use jQuery just to do a fucking POST call and don't use Bootstrap just because you're fucking lazy.&lt;/p&gt;
&lt;h2 id="the-least-you-can-do"&gt;The least you can do&lt;a class="headerlink" href="#the-least-you-can-do" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="base"&gt;Base&lt;a class="headerlink" href="#base" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In order for your website to be quick, it needs to have a solid, lightweight base. To ensure this, &lt;em&gt;my&lt;/em&gt; solution was to create &lt;a href="https://0xff.nu/why-saisho"&gt;my own website engine&lt;/a&gt; that will fit &lt;em&gt;my needs&lt;/em&gt;. You, of course, don't have to do this, but you do have to take your base into account as it's probably the most important aspect.&lt;/p&gt;
&lt;p&gt;WordPress is bloated&lt;sup id="fnref:2-1"&gt;&lt;a class="footnote-ref" href="#fn:2-1"&gt;1&lt;/a&gt;&lt;/sup&gt;. You need a plugin for even the most basic things which make the platform even heavier. This is not to say that WordPress is bad per se, but it is more often than not an overkill solution just to handle your blog or journal.&lt;/p&gt;
&lt;p&gt;If you can afford it, use a static site builder like &lt;a href="https://www.11ty.dev/"&gt;11ty&lt;/a&gt; or literally anything from &lt;a href="https://www.staticgen.com/"&gt;StaticGen&lt;/a&gt;. If you need a CMS, use lighter solutions like &lt;a href="https://www.bludit.com/"&gt;Bludit&lt;/a&gt;, &lt;a href="https://getgrav.org/"&gt;Grav&lt;/a&gt; or &lt;a href="https://automad.org/"&gt;Automad&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="accessibility"&gt;Accessibility&lt;a class="headerlink" href="#accessibility" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Making your website more accessible to different kinds of people probably was not in your list of considerations, but you can now help change this. There are tons of small things you can do which will ensure a lot more people can read your website comfortably.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Animations&lt;/strong&gt; - Want to use animations? Great! But please note not everybody likes (or can stomach) this fucking trash:&lt;/p&gt;
&lt;video controls width="450"&gt;
    &lt;source src="https://0xff.nu/i/Disastrous-4da830c339b59b9b.webm"
            type="video/webm"&gt;
    Sorry, your browser doesn't support embedded videos.
&lt;/video&gt;
&lt;p&gt;Animations, at worst, need to compliment your content and &lt;strong&gt;enhance&lt;/strong&gt; the user experience, and at best not to be used at all.
Still want to use them (in moderation, of course)? Sure, BUT also use the &lt;code&gt;prefers-reduced-motion&lt;/code&gt; &lt;sup id="fnref:2-2"&gt;&lt;a class="footnote-ref" href="#fn:2-2"&gt;2&lt;/a&gt;&lt;/sup&gt; media query. This way, those who do not wan't to see animations will not be forced to do so.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Colors&lt;/strong&gt; - Use tools like &lt;a href="https://color.a11y.com/"&gt;this&lt;/a&gt; to make sure the colors you are using are contrasty enough.
While some say dark mode (or night mode) is not important, it is becoming way more requested and needed. Besides, it is now easier than ever to implement using the &lt;code&gt;prefers-color-scheme&lt;/code&gt;&lt;sup id="fnref:2-3"&gt;&lt;a class="footnote-ref" href="#fn:2-3"&gt;3&lt;/a&gt;&lt;/sup&gt; media query, so why not add it?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fonts&lt;/strong&gt; - Avoid webfonts if you can. The system stack is usable enough for most people. If you are using webfonts, don't use unreadable shit like this:
&lt;img alt="Unreadable" src="https://0xff.nu/i/Tubby-ae0ddc24569cabab.png" /&gt;&lt;/p&gt;
&lt;p&gt;Relevant reading:
- &lt;a href="https://alistapart.com/article/designing-safer-web-animation-for-motion-sensitivity/"&gt;Designing Safer Web Animation For Motion Sensitivity&lt;/a&gt;.
- &lt;a href="https://css-tricks.com/introduction-reduced-motion-media-query/"&gt;An Introduction to the Reduced Motion Media Query&lt;/a&gt;.
- &lt;a href="https://medium.com/hackernoon/web-fonts-when-you-need-them-when-you-dont-a3b4b39fe0ae"&gt;Web fonts: when you need them, when you dont&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="frameworks"&gt;Frameworks&lt;a class="headerlink" href="#frameworks" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Want to use a framework? Don't. &lt;strong&gt;Absolutely have&lt;/strong&gt; to use CSS &amp;amp; JS frameworks? Use them wisely.
How does, for example, loading 500-fucking-kilobytes for 5 social icons makes any sense?
&lt;img alt="this is 500kb" src="https://0xff.nu/i/Secondary-d154d301072c74d3.png" /&gt;&lt;/p&gt;
&lt;p&gt;Write your own CSS according to your/your website's needs. Only add classes you're going to use. Optimize.&lt;/p&gt;
&lt;p&gt;If you're only using jQuery (31kb) to do ONE thing, I'm sure as hell you can manage to do it using vanilla JS. Need a small framework to make things easier? Check out &lt;a href="https://github.com/fabiospampinato/cash"&gt;Cash&lt;/a&gt; or &lt;a href="https://umbrellajs.com/"&gt;UmbrellaJS&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="images"&gt;Images&lt;a class="headerlink" href="#images" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Images are there to compliment the rest of your content. Unless I'm looking at your portfolio of visual arts, don't make me download a megabyte photo of your mug.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Optimize&lt;/strong&gt; - there's no fucking reason for you to force me to load unnecessary data, for example the illustration &lt;a href="https://merichard123.github.io/"&gt;here&lt;/a&gt; provides no additional value yet weighs 26% of the total page size.
FFS the same image in WEBP is 132kB, which is a 31.6% reduction in size and it only took me 5 fucking seconds to do this.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Resize&lt;/strong&gt; - The profile image &lt;a href="http://www.pierrealexandreholliger.fr/"&gt;here&lt;/a&gt; for example is 1728x1152 pixels yet you're limiting it to 30% in CSS, thus making your visitors download more data than is actually required. WHY? 5 fucking seconds to resize it to 600x400 and optimize and it's a miniscule 17.9 kB instead of 95.1kB, and all it took is some caring.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lazy loading&lt;/strong&gt; - Utilize &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Performance/Lazy_loading"&gt;lazy-loading&lt;/a&gt; on all the images that you use. It costs you nothing, yet helps a lot.&lt;/p&gt;
&lt;h2 id="what-else-can-i-do"&gt;What else can I do?&lt;a class="headerlink" href="#what-else-can-i-do" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This all depends on how much you care. If you care about your website, and you actually put some time in crafting it rather than throwing a bunch of crap together - it will look and perform great.
Make sure to check out &lt;a href="https://www.nginx.com/blog/nginx-caching-guide/"&gt;client-side caching&lt;/a&gt; (if your HTML won't change, you could try caching it as well), preload/prefetch&lt;sup id="fnref:2-4"&gt;&lt;a class="footnote-ref" href="#fn:2-4"&gt;4&lt;/a&gt;&lt;/sup&gt; resources, minification, pre-compressing your resources, read what &lt;a href="https://daverupert.com/2020/03/maintaining-performance/"&gt;others&lt;/a&gt; &lt;a href="https://www.kizu.ru/a-bit-of-performance/"&gt;have done&lt;/a&gt;, and try to stay on top of whats new in web technologies.&lt;/p&gt;
&lt;p&gt;The main point I'm trying to get across is this - Experiment to your heart's content, but please give a shit when it comes to a publicly available website, your visitors are not your test subjects. They would rather read what you have to say than bask at the unholy abomination that is your fancy fucking React APP. &lt;/p&gt;
&lt;h3 id="further-reading"&gt;Further Reading&lt;a class="headerlink" href="#further-reading" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kokorobot.ca/site/leanerweb.html"&gt;Bandwidth Conservation Society&lt;/a&gt; by Rekka Bellum.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.dev/content-visibility/"&gt;&lt;code&gt;content-visibility&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.dev/service-worker-caching-and-http-caching/"&gt;Service worker caching and HTTP caching&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:2-1"&gt;
&lt;p&gt;This is not my opinion. This is a fact. Articles like &lt;a href="https://devdojo.com/ramadan-byalk/useful-code-snippets-for-wordpress"&gt;this&lt;/a&gt; exist because of how bloated WP is.&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2-2"&gt;
&lt;p&gt;https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-2" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2-3"&gt;
&lt;p&gt;https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-3" title="Jump back to footnote 3 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2-4"&gt;
&lt;p&gt;https://www.digitalocean.com/community/tutorials/html-preload-prefetch&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-4" title="Jump back to footnote 4 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><pubDate>Wed, 12 Aug 2020 00:00:00 -0000</pubDate></item><item><title>Suteba</title><link>https://0xff.nu/suteba/</link><description>&lt;p&gt;&lt;img alt="Suteba Logo" src="https://paulglushak.com/bl-content/uploads/pages/dd22ef7a5e5569727a1fa0872c5155ff/suteba.png" /&gt;
My day job requires me to perform troubleshooting on customer issues, some of which may include trying to understand what might be wrong in an API request payload.&lt;/p&gt;
&lt;p&gt;While I could have used a service like &lt;a href="http://requestbin.net/"&gt;requestbin.net&lt;/a&gt;, it wouldn't be much of a learning experience, would it?&lt;/p&gt;
&lt;p&gt;The solution, then, was to make my own little tool that I could use to help myself investigate these issues, which I have also decided to share with you guys, in case you might find it useful.&lt;/p&gt;
&lt;p&gt;I present &lt;em&gt;Suteba&lt;/em&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Simple and light. No trackers. No bullshit.&lt;/li&gt;
&lt;li&gt;You own all the data.&lt;/li&gt;
&lt;li&gt;Multiple bins/buckets/dumps/whatever.&lt;/li&gt;
&lt;li&gt;Listing feature of requests per bin.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; Features are sparse to make Suteba simple and light. You're more than welcome to suggest additions, but please keep the simplicity in mind.&lt;/p&gt;
&lt;p&gt;Available on
&lt;a href="https://git.sr.ht/~hxii/suteba"&gt;SourceHut&lt;/a&gt;
&lt;a href="https://github.com/hxii/suteba"&gt;GitHub&lt;/a&gt;&lt;/p&gt;</description><pubDate>Mon, 27 Jul 2020 00:00:00 -0000</pubDate></item><item><title>Pursuing Speed, Pt. 2</title><link>https://0xff.nu/speed-pt2/</link><description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: Nothing in this article/rant is meant to offend anyone. If your wesbite is used as an example know that I don't think you're bad at what you do or have anything against you.
This is my opinion, and you're welcome to disagree with it. Don't advocate over-engineering without a purpose and don't spread bad advice.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In my previous entry, &lt;a href="/speed"&gt;Pursuing Speed&lt;/a&gt;, I feel like even though I got my point across (I'd like to believe I did) I didn't articulate my thoughts in a sufficient manner.
In this addendum, I'd like to further elaborate about the state of the web.&lt;/p&gt;
&lt;p&gt;In today's world -- a world of abundance and plenty, it's easy to get lost in the plethora of available resources and fast connections and become lazy and dependent on these resources, all while forgetting your craft and why is it you started doing whatever it is you're doing in the first place.&lt;/p&gt;
&lt;p&gt;People like Colby Fayock saying &lt;a href="https://www.colbyfayock.com/2020/07/youre-allowed-to-overengineer-your-blog/"&gt;you're allowed to over-engineer your blog&lt;/a&gt; couldn't be more wrong (at least in the current phrasing), basically saying you can just do what-fucking-ever because it's educational for YOU.
While yes, you can use React, jQuery and whatever fucking library you wish to hone YOUR skills, dumping all these overkill libraries, frameworks, trackers and huge fucking images on your visitors is NOT okay.&lt;/p&gt;
&lt;h2 id="what-the-fuck-is-accessibility-even"&gt;What the fuck is accessibility, even?&lt;a class="headerlink" href="#what-the-fuck-is-accessibility-even" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What people like Colby Fayock are saying, is that websites like &lt;a href="https://merichard123.github.io/"&gt;this&lt;/a&gt; are okay. That it is, in essence, okay to force your visitors to load 1.6Mb of resources just to show them 1084b (yes, bytes) of relevant information (on the front page). That's 0.06%.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Holy fucking unreadable font, Batman!" src="https://0xff.nu/i/Tubby-ae0ddc24569cabab.png" /&gt;&lt;/p&gt;
&lt;p&gt;Somehow loading FontAwesome Brands font, an image with no added value and honestly an unreadable Google Font is more fucking important than adding a dark theme to your website, properly designing for mobile, or, you know, if you &lt;strong&gt;truly&lt;/strong&gt; want to be hip, fucking researching about &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Network_Information_API"&gt;Network Information API&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="glorious-overkill"&gt;Glorious overkill&lt;a class="headerlink" href="#glorious-overkill" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Broken HTTPS cert aside, websites like &lt;a href="https://cs.ambadiritik.tech/"&gt;this&lt;/a&gt; are completely fucking useless if you can't (or don't want to) load JavaScript. So you know what? Fine, let's load JS.
What did we get? We're loading 256kb for this much fucking content:
&lt;img alt="Image showing disproportionate content to page size" src="https://0xff.nu/i/Cold-2a380d37a67d0e9c.png" /&gt;
Fucking great. 622b of mostly irrelevant data. &lt;strong&gt;That's 0.24% of what you're actually fucking loading.&lt;/strong&gt;
But hey, having a fucking shiny React website is more important, right? For personal development, yeah?&lt;/p&gt;
&lt;h2 id="i-cant-even"&gt;I can't even&lt;a class="headerlink" href="#i-cant-even" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As a last example, we have people like Miranda Limonczenko who preach about &lt;a href="https://dev.to/mlimonczenko/why-clean-code-is-still-a-classic-3n3a"&gt;Clean Code&lt;/a&gt; who's website is, ready for it? &lt;strong&gt;8 point fucking 3 megabytes large&lt;/strong&gt;.
That's for the front fucking page. The &lt;strong&gt;entirety&lt;/strong&gt; of Shakespeare's works only occupy about 5.6mb.&lt;/p&gt;
&lt;p&gt;&lt;img alt="20 seconds to load on Fast 3G" src="https://0xff.nu/i/Real-d9294c8a9bce95b1.png" /&gt;&lt;/p&gt;
&lt;p&gt;I'm not even going to talk about the fact SquareSpace is being used here. Or that it's ridden with trackers. Or that it would take me fucking 18 seconds to load this monstrosity with a Fast 3G connection just to see promotional garbage on the front page.&lt;/p&gt;
&lt;h2 id="over-engineering"&gt;Over-engineering&lt;a class="headerlink" href="#over-engineering" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Go on, listen to people like Colby, over-engineer ahead, shove 10 frameworks, 5 million libraries and all the fucking tracking scripts you want - at &lt;strong&gt;your own&lt;/strong&gt; expense.
Your visitors are &lt;strong&gt;not&lt;/strong&gt; your testing group. Their time is not free and nor is their data plan.&lt;/p&gt;</description><pubDate>Thu, 23 Jul 2020 00:00:00 -0000</pubDate></item><item><title>Pursuing Speed</title><link>https://0xff.nu/speed/</link><description>&lt;p&gt;Continuing my rambling about &lt;a href="https://0xff.nu/pursuing-minimalism"&gt;pursuing minimalism&lt;/a&gt;, I'd like to also say a few words about speed having "finished" rewriting my own website engine, once again.&lt;/p&gt;
&lt;p&gt;Minimalism and speed (at least when it comes to the web) became a sort of obsession of mine, and I always (try to) stay up to date about any new developments in web development, optimization, caching and other ways of improving speed.&lt;/p&gt;
&lt;p&gt;Sure, WordPress can be made fast-er (&lt;a href="https://darryldias.me/2015/lightweight-wordpress-setup/"&gt;leaving&lt;/a&gt; &lt;a href="https://copyblogger.com/make-wordpress-faster/"&gt;ironic&lt;/a&gt; &lt;a href="https://www.sparringmind.com/speed-up-wordpress/"&gt;snake&lt;/a&gt; &lt;a href="https://www.collectiveray.com/speed-up-wordpress"&gt;oil&lt;/a&gt; &lt;a href="https://websitesetup.org/how-to-speed-up-wordpress/"&gt;aside&lt;/a&gt;), but once your base is bloated&lt;sup id="fnref:2-1"&gt;&lt;a class="footnote-ref" href="#fn:2-1"&gt;1&lt;/a&gt;&lt;/sup&gt; you will never stop optimizing the behemoth by either removing built-in functionality&lt;sup id="fnref:2-2"&gt;&lt;a class="footnote-ref" href="#fn:2-2"&gt;2&lt;/a&gt;&lt;/sup&gt;, installing more plugins e.g. cache, finding clean themes or a combination of the above.&lt;/p&gt;
&lt;p&gt;Why, then, not start from a clean base? That is exactly why more and more people nowadays are turning to WordPress alternatives such as &lt;a href="https://www.bludit.com/"&gt;Bludit&lt;/a&gt;, &lt;a href="https://ghost.org/"&gt;Ghost&lt;/a&gt;, &lt;a href="https://statamic.com/"&gt;Statamic&lt;/a&gt; and others as well as static website builders such as &lt;a href="https://www.11ty.dev/"&gt;11ty&lt;/a&gt;, &lt;a href="https://gohugo.io/"&gt;Hugo&lt;/a&gt; and &lt;a href="https://www.gatsbyjs.org/"&gt;Gatsby&lt;/a&gt; in which it is easier to control what is being loaded and served.&lt;/p&gt;
&lt;p&gt;You can of course take it one step further, if you're really inclined towards speed and controlling your own data and delivery. More on this later.&lt;/p&gt;
&lt;h2 id="state-of-the-web"&gt;State of the web&lt;a class="headerlink" href="#state-of-the-web" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The thing is, there is, in my opinion a general disregard towards website sizes and loading speeds: huge fucking &lt;abbr title="Cascading Style Sheets"&gt;CSS&lt;/abbr&gt; frameworks, unoptimized images, unnecessary JS libraries and the list goes on.&lt;/p&gt;
&lt;p&gt;I recently found instant.page&lt;sup id="fnref:2-3"&gt;&lt;a class="footnote-ref" href="#fn:2-3"&gt;3&lt;/a&gt;&lt;/sup&gt; and was immediately interested in the type of websites that might be using it.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://resume.benc.io/"&gt;Here&lt;/a&gt; we have someone's resume that is just one page, but it loads 7 JS files, 1.7kb of &lt;abbr title="Cascading Style Sheets"&gt;CSS&lt;/abbr&gt; and 30kb of fonts. All for &lt;strong&gt;one page&lt;/strong&gt;, to a total of 100kb. At least the damn SVGs are inline instead of loading fucking FontAwesome.&lt;/p&gt;
&lt;p&gt;Or &lt;a href="https://onemin-impact.github.io/"&gt;this&lt;/a&gt; placeholder for someone's blog. How bad is it, you ask? 288kb transferred with no meaningful information presented.&lt;/p&gt;
&lt;p&gt;&lt;img alt="288kb for this? Really?" src="https://0xff.nu/i/Unlined-15763c51861e33b5.png" title="288kb for this? Really?" /&gt;&lt;/p&gt;
&lt;p&gt;Things are bad, but they don't have to be, as soon as people start caring without just throwing a bunch of shit together and calling it a website.&lt;/p&gt;
&lt;h2 id="what-did-i-do"&gt;What did I do?&lt;a class="headerlink" href="#what-did-i-do" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Preface&lt;/strong&gt;: What I did was, in a sense, take things to the extreme. I do not think or am saying this level of minimalism is good for &lt;em&gt;everyone&lt;/em&gt;, but you can take inspiration and ideas from what I did and implement them in your platform of choice.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The base - Instead of using a ready and working platform I decided to write &lt;a href="https://paulglushak.com/saisho"&gt;my own&lt;/a&gt;. This allows me to control &lt;strong&gt;everything&lt;/strong&gt; without relying on third parties when it comes to features.
   &lt;abbr title="Cascading Style Sheets"&gt;CSS&lt;/abbr&gt; was written by hand and only the necessary blocks are present.
   This may not be for everyone, as for better or worse, making it work is up to you (so is security).&lt;/li&gt;
&lt;li&gt;The bloat - There is none. I am using nothing and loading nothing besides the necessities and the page content. No &lt;abbr title="Cascading Style Sheets"&gt;CSS&lt;/abbr&gt; frameworks, no JS libraries (sans instant.page&lt;sup id="fnref2:2-3"&gt;&lt;a class="footnote-ref" href="#fn:2-3"&gt;3&lt;/a&gt;&lt;/sup&gt;). Nothing.&lt;/li&gt;
&lt;li&gt;The speed - A couple of speed optimizations were done. Some of them may be placebo.&lt;/li&gt;
&lt;li&gt;nginx serves everything with Brotli compression enabled.&lt;/li&gt;
&lt;li&gt;Pages are processed with PHP and the output buffer response is cached as &lt;abbr title="HyperText Markup Language"&gt;HTML&lt;/abbr&gt; for 3600 seconds.&lt;/li&gt;
&lt;li&gt;Pages are cached in browser using:
     &lt;code&gt;header('cache-control:public, max-age='.CACHE_TIME.', immutable');&lt;/code&gt;
     Memcached was also considered.&lt;/li&gt;
&lt;li&gt;Last Modified header is also sent:
     &lt;code&gt;header('Last-Modified:' . gmdate('D, d M Y H:i:s ', @filemtime($filePath)) . 'GMT');&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Links are prefetched once hovered using &lt;a href="https://github.com/instantpage/instant.page"&gt;instant.page&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Images are optimized, dithered and stored locally.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All these allow pages on Saisho&lt;sup id="fnref:2-4"&gt;&lt;a class="footnote-ref" href="#fn:2-4"&gt;4&lt;/a&gt;&lt;/sup&gt; to be loaded almost instantaneously, something I am really proud of.&lt;/p&gt;
&lt;h2 id="what-can-you-do"&gt;What can you do?&lt;a class="headerlink" href="#what-can-you-do" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Start caring.&lt;/p&gt;
&lt;p&gt;What you do from there is up to you - optimize WordPress to no end, use static website generators, write your custom engine, write static &lt;abbr title="HyperText Markup Language"&gt;HTML&lt;/abbr&gt; websites or whatever else works for you.&lt;/p&gt;
&lt;p&gt;But care about what you're doing and take into account the people who will be visiting your website and their time.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:2-1"&gt;
&lt;p&gt;Rightfully so as WordPress is a platform, not a tailor-made solution, but more often than not it's overkill for the average folk.&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2-2"&gt;
&lt;p&gt;Functionality here is debatable. jQuery for example is loaded &lt;a href="https://wordpress.stackexchange.com/a/91734"&gt;all the time&lt;/a&gt;.&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-2" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2-3"&gt;
&lt;p&gt;instant.page: https://github.com/instantpage/instant.page&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-3" title="Jump back to footnote 3 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;a class="footnote-backref" href="#fnref2:2-3" title="Jump back to footnote 3 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2-4"&gt;
&lt;p&gt;&lt;a href="https://paulglushak.com/saisho"&gt;Saisho&lt;/a&gt; is my semi-static website engine which you are seeing now.&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-4" title="Jump back to footnote 4 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><pubDate>Mon, 20 Jul 2020 00:00:00 -0000</pubDate></item><item><title>Making my own KMS</title><link>https://0xff.nu/making-my-own-kms/</link><description>&lt;h2 id="preface"&gt;Preface&lt;a class="headerlink" href="#preface" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This whole thing is my personal experience and is probably an incorrect or ineffective (let alone the code itself being a fucking mess) way of doing things. What may work for me may not work for others. This is why, at least currently, this project will not be available publicly.&lt;/p&gt;
&lt;p&gt;Knowledge is important. Saving knowledge is even more important, especially for people like me who have a hard time remembering things sometimes.&lt;/p&gt;
&lt;p&gt;In order to assist myself to remember things as well as become more organized, I decided to implement the "second brain" approach of creating a (private) knowledge dump where I will save notes, ideas and code snippets.&lt;/p&gt;
&lt;h2 id="the-initial-idea"&gt;The initial idea&lt;a class="headerlink" href="#the-initial-idea" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before I started working on my KMS, I only vaguely knew what I wanted to accomplish thinking my KMS will be a constantly evolving, living thing. That said, I did have something in mind: ease of use and fluid categorization. &lt;/p&gt;
&lt;p&gt;What do I mean by fluid categorization? Opposed to platforms like WordPress that use a set taxonomies, my KMS should have a fluid document relationship - A document can, for example, one day belong to a Code Snippets category and to Project X on another once I actually get to analyze and "categorize" it.&lt;/p&gt;
&lt;p&gt;This would be implemented by using a format such as &lt;code&gt;type:value&lt;/code&gt; in the header. So, like in the aforementioned example, a document can be &lt;code&gt;category:code-snippets&lt;/code&gt; one day and &lt;code&gt;project:x&lt;/code&gt; on another.&lt;/p&gt;
&lt;p&gt;I called these "links", for now.&lt;/p&gt;
&lt;h2 id="the-stack"&gt;The Stack&lt;a class="headerlink" href="#the-stack" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Everything is done using HTML, CSS and PHP. JavaScript only exists to enable &lt;a href="https://highlightjs.org/"&gt;highlight.js&lt;/a&gt; as well as &lt;a href="https://github.com/Ionaru/easy-markdown-editor"&gt;EasyMDE&lt;/a&gt;.
In quite a few places JS would make sense (AJAX search, for example), but for the time being I'd like to avoid using JS.&lt;/p&gt;
&lt;p&gt;I initially thought of making this a very lightweight system, but as I kept adding things I quickly realized I should start making this into proper object-oriented software. I'm not there yet as (due to not actually being a programmer) I don't quite understand all the concepts yet.&lt;/p&gt;
&lt;h2 id="document-format"&gt;Document Format&lt;a class="headerlink" href="#document-format" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As I got used to using MarkDown, I have decided to use it for my KMS albeit with some custom properties that were created in order to avoid any sort of database storage of document related information (either relational or flat).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The reasoning:&lt;/em&gt; This was done so that all the documents are essentially self-contained and that all relevant information is stored in case I decide to switch platforms or in case the documents are viewed externally.
The only thing that is currently contained elsewhere are the link descriptions&lt;sup id="fnref:2-1"&gt;&lt;a class="footnote-ref" href="#fn:2-1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Every document would include a header such as:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[[title]] Document Title
[[date]] yyyy-mm-dd
[[link]] type:value
[[description]] Optional description
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which will be parsed once the document has been read. This means that all links are created on runtime.&lt;/p&gt;
&lt;p&gt;After some reading and research (and after creating the lame support for tags), I decided to drop the custom properties and adopted a YAML header instead:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
title: Optional Title (Otherwise first H1)
link: type:value
date: yyyy-mm-dd
description: optional description
tags: comma,delimited,tags
---
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I quickly learned that I couldn't parse YAML in PHP and would need a library to do so. So I decided, as with many other things, to write my own:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;private function parse_yaml(string &amp;amp;$str)
{
    $parsed = [];
    preg_match(&amp;quot;'---(.+?)---'si&amp;quot;, $str, $yaml);
    if (!isset($yaml[0])) return false;
    $str = str_replace($yaml[0], '', $str);
    $parsed['body'] = $str;
    $yaml = trim($yaml[0]);
    preg_match_all(&amp;quot;'(\w+):\s?(.+)'m&amp;quot;, $yaml, $yaml_attribs, PREG_SET_ORDER);
    foreach ($yaml_attribs as $attribute) {
        $parsed[$attribute[1]] = trim($attribute[2]);
    }
    return (object) $parsed;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The way I did it is less than ideal, but it works in this scenario which, in turn, is good enough for me.&lt;/p&gt;
&lt;h2 id="usage"&gt;Usage&lt;a class="headerlink" href="#usage" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If something is not comfortable to use, you'll stop using it shortly after. This means, especially for me, that comfort is paramount in order to force myself to make recording knowledge a habit.&lt;/p&gt;
&lt;p&gt;I started from a local instance running in my computer, which would, obviously, prove to be less then ideal as I couldn't record anything when my computer is either off or when I'm away. This prompted me to upload a copy of the code to my VPS in order to start using it.&lt;/p&gt;
&lt;p&gt;This, in turn, brought up the need for a couple more improvements in order to make my KMS more usable:&lt;/p&gt;
&lt;h3 id="responsive-ui"&gt;Responsive UI&lt;a class="headerlink" href="#responsive-ui" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As my KMS has basically no UI and everything is text based, this improvement was easy to implement but at the same time was most likely the most important one to accomplish first.&lt;/p&gt;
&lt;p&gt;A couple of CSS rules later and, albeit not the easiest to use, I could use the KMS from my phone as well.&lt;/p&gt;
&lt;p&gt;Editing still proves to be a challenge sometimes as, after all, this is not a native application and there's a severe lack of interactivity in the shape of JS.&lt;/p&gt;
&lt;h3 id="tags"&gt;Tags&lt;a class="headerlink" href="#tags" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Tags provide one more way to, well, tag documents. For example, a document with the &lt;code&gt;link: category:recipes&lt;/code&gt; link might have &lt;code&gt;tags: sweet,easy,quick&lt;/code&gt;.
Currently, tags are very underused and I'm still thinking of the best way to use them appropriately.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;ToDo&lt;/em&gt; - Use tags properly.&lt;/p&gt;
&lt;h3 id="search"&gt;Search&lt;a class="headerlink" href="#search" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This was a very important task to accomplish as, with time, as the collection of documents grows, finding a particular document or even a piece of information will become harder.&lt;/p&gt;
&lt;p&gt;Me being me, instead of relying on things that actually &lt;strong&gt;work&lt;/strong&gt;, I decided to write my own scored search system. It's currently still broken and requires a lot of improvement, but it works for the most part.&lt;/p&gt;
&lt;p&gt;The results are scored in the following way:
- &lt;strong&gt;Tags&lt;/strong&gt; - A tag match is 5 points.
- &lt;strong&gt;Title&lt;/strong&gt; - A full title match is 1 point. &lt;code&gt;similar_text()&lt;/code&gt; is used for partial matches where 55% match and above is 0.5 points and a 75% match and above is 1 point.
- &lt;strong&gt;Content&lt;/strong&gt; - A full match returns the word length of the query worth in points (so "quick recipe" will return 2 points). Each separately matched word is 0.25 points.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;public function find(string $search_string)
{
        $this-&amp;gt;search_string = urldecode($search_string);
        $this-&amp;gt;results = [];
        foreach ($this-&amp;gt;pages as $key =&amp;gt; $page) {
            if ($page-&amp;gt;tags) {
                    $score = $this-&amp;gt;check_tags($page-&amp;gt;tags, $this-&amp;gt;search_string);
            } else {
                    $score = 0;
            }
            $score += $this-&amp;gt;check_title($page-&amp;gt;title, $this-&amp;gt;search_string);
            $score += $this-&amp;gt;check_content($page-&amp;gt;content, $this-&amp;gt;search_string);
            if ($score &amp;gt; 0) {
                    $page-&amp;gt;score = $score;
                    $this-&amp;gt;results[] = $page;
            }
        }
        return usort($this-&amp;gt;results, function ($a, $b) {
                return $b-&amp;gt;score &amp;lt;=&amp;gt; $a-&amp;gt;score;
        });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;ToDo&lt;/em&gt; - Optimize the searching and scoring method for more accurate and/or diverse results.&lt;/p&gt;
&lt;h3 id="internal-links"&gt;Internal Links&lt;a class="headerlink" href="#internal-links" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Internal links had to be implemented through a custom format (&lt;code&gt;{{@link-slug:optional title}}&lt;/code&gt;) and are parsed at runtime. Someday I will figure out how to do these Wikipedia style (&lt;code&gt;[[link slug]]&lt;/code&gt;).&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;preg_match_all('/{{@([^:][\w-]+)(?::(.+))?}}/', $data, $intlink_matches, PREG_SET_ORDER);
foreach ($intlink_matches as $match) {
        $data = str_replace($match[0], '&amp;lt;a href=&amp;quot;' . DS . $match[1] . '&amp;quot;&amp;gt;' . $match[2] ?? $match[1] . '&amp;lt;/a&amp;gt;', $data);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;ToDo&lt;/em&gt; - Perform search on title instead of providing slug manually.&lt;/p&gt;
&lt;h2 id="ease-of-use-and-other-things"&gt;Ease of use and other things&lt;a class="headerlink" href="#ease-of-use-and-other-things" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id="quick-editing"&gt;Quick Editing&lt;a class="headerlink" href="#quick-editing" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;One more thing that prompted me to use a &lt;a href="#document-format"&gt;YAML header&lt;/a&gt; instead of custom properties was trying to make the process of creating new documents as easy as possible. This includes providing little to no information besides the content when creating a new document.&lt;/p&gt;
&lt;p&gt;For this exact reason, when creating a new document nothing is mandatory: filenames (IDs) are generated using a &lt;code&gt;Ymdhis&lt;/code&gt; date format (e.g. 20200608023521, similar to ZettelKasten IDs), titles are taken from the first H1 occurrence OR the file ID, the default link is &lt;code&gt;:inbox&lt;/code&gt; and so on.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The reasoning:&lt;/em&gt; All these allow me to just write down whatever information I need to record and get back to it later whenever I've got more time or when I have access to my computer.&lt;/p&gt;
&lt;h3 id="image-upload"&gt;Image Upload&lt;a class="headerlink" href="#image-upload" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;One more thing that I figured out I needed was image upload, which, currently is working but is very rudimentary.
The process:
1. File is uploaded via a form using PHP POST.
2. File is renamed to &lt;code&gt;document-slug_ID.ext&lt;/code&gt; where ID is the last image ID + 1. This will ensure images are still "linked" to their pages even if viewed separately.
3. File is moved to uploads folder.
4. Image is appended in MD format to the page content.
5. Document is saved and reloaded.&lt;/p&gt;
&lt;p&gt;This is less than ideal, but again - I'm not using JavaScript.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;public static function process_image_upload(string $page_name, array $files)
    {
        $allowed_types = [
            'jpg' =&amp;gt; 'image/jpeg',
            'png' =&amp;gt; 'image/png',
        ];
        $image_extension = pathinfo($files['imageupload']['name'], PATHINFO_EXTENSION);
        if (!array_key_exists($image_extension, $allowed_types) || $allowed_types[$image_extension] != $files['imageupload']['type']) {
            echo 'File type not allowed!';
            return false;
        }
        $last_index = self::get_last_page_image_index($page_name) ?? 0;
        $new_image_name = $page_name . '_' . ($last_index + 1) . '.' . $image_extension;
        if (move_uploaded_file($files['imageupload']['tmp_name'], UPLOAD_PATH . $new_image_name)) {
            return '//' . HOME_URL . DS . UPLOADS_FOLDER . DS . $new_image_name;
        } else {
            echo 'Error uploading image!';
            return false;
        }
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;The reasoning:&lt;/em&gt; Sometimes, visual representation is required, as in the case with recipes, for example. External image hosting will not do, especially if the KMS is completely internal.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;ToDo&lt;/em&gt; - Resizing and optimizing images post upload.&lt;/p&gt;
&lt;h3 id="page-relations"&gt;Page Relations&lt;a class="headerlink" href="#page-relations" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Besides the page link (&lt;code&gt;link: page:page-slug&lt;/code&gt; which basically defines a "sub-document"), I took some inspiration from &lt;a href="https://notes.andymatuschak.org/About_these_notes?stackedNotes=z21cgR9K3UcQ5a7yPsj2RUim3oM2TzdBByZu"&gt;Andy Matuschak's Notes&lt;/a&gt; and implemented related documents.&lt;/p&gt;
&lt;p&gt;These are also rudimentary and rely on the YAML header, but they work and allow me to link pages together.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;ToDo&lt;/em&gt; - Identify the internal link and create the connection between pages at runtime, instead of having to specify the related documents manually.&lt;/p&gt;
&lt;h3 id="external-links"&gt;External Links&lt;a class="headerlink" href="#external-links" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To quickly add interesting links and resources, my KMS can also be used as a sort of bookmarking system, where I can also give a bookmark it's own context. The only thing that changes, really, is that external links get an extra attribute in the header: &lt;code&gt;href: https://url&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;a class="headerlink" href="#conclusion" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I'm not done. I am still learning what are the best ways to do personal knowledge management as well as how to write proper PHP code.&lt;/p&gt;
&lt;p&gt;You might see this post updated in the future once I think of other things :)&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:2-1"&gt;
&lt;p&gt;Descriptions are plaintext strings tied to a link (e.g. &lt;code&gt;":recipes":"Assortment of random recipes. To be categorized."&lt;/code&gt;) and exist in a &lt;code&gt;descriptions.json&lt;/code&gt; file inside the data folder.
They will be eventually replaced by something called descriptive documents.&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><pubDate>Mon, 06 Jul 2020 00:00:00 -0000</pubDate></item><item><title>5 years</title><link>https://0xff.nu/5-years/</link><description>&lt;p&gt;"Where do you see yourself in 5 years?" is a silly, loaded question that I unfortunately find myself struggling with answering every time I go for an interview.&lt;/p&gt;
&lt;p&gt;The interviewers &lt;em&gt;usually&lt;/em&gt; dont care about your fucking grandiose plans five years from now. All they want to hear is that you'll be there, doing whatever they're hiring you to do.&lt;/p&gt;
&lt;p&gt;Five years ago I was dreading every day while working in IT. If you asked me back then where I'd see myself in five years I sure as hell wouldn't have told you I'd be working in highly technical customer support and doing development on the side.&lt;/p&gt;
&lt;p&gt;And the thing is - I can't lie. When I get asked this question, my answer usually is "I don't know" followed by an explanation that I like many things and that I'm learning from everything I can.
If you expect me to lie and answer "here, doing the same fucking thing" you're out of your mind, but if I answer truthfully, I am probably seen as an "unsafe bet" despite my intention being that I'm open to &lt;em&gt;different&lt;/em&gt; opportunities in your company.&lt;/p&gt;
&lt;p&gt;So, then, what is the point? What is the answer you seek? What is the &lt;em&gt;"correct"&lt;/em&gt; answer?&lt;/p&gt;
&lt;p&gt;In five years I will know more (in whichever direction), do more, and get paid more. I want to &lt;strong&gt;learn&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I guess I am trying to make sense of something nonsensical.&lt;/p&gt;</description><pubDate>Sun, 21 Jun 2020 00:00:00 -0000</pubDate></item><item><title>Learning to be organized</title><link>https://0xff.nu/personal-management/</link><description>&lt;p&gt;I'm not an artsy person. Can't do it. This is why I perceive self-organization as an art.&lt;/p&gt;
&lt;p&gt;Seeing as I'm not a very organized person and suddenly being forced to have extra spare time, I've decide to do just that - learn the art of self organization.&lt;/p&gt;
&lt;p&gt;Considering I'm not yet used to this idea of being organized, instead of using tools and services that exist, I've decided to make my own.&lt;/p&gt;
&lt;h2 id="shigoto"&gt;Shigoto&lt;a class="headerlink" href="#shigoto" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Todo apps are everywhere. But one format makes it easy to have a todo list in plaintext - &lt;a href="http://todotxt.org/"&gt;todo.txt&lt;/a&gt;.
I've decided to give it a try, and made a parser/manager that I myself use to try and organize (and recently, track time!) my tasks.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Shigoto todo.txt manager" src="https://0xff.nu/i/firefox_Gv0GlA12To.png" /&gt;&lt;/p&gt;
&lt;p&gt;Currently I use it sparingly, but I try and keep at it. My main problem is it's not very well adapted to a mobile view just yet, so managing tasks on my phone is annoying. Another would be synchronization.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://paulglushak.com/shigoto"&gt;Shigoto&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="personal-wiki"&gt;Personal Wiki&lt;a class="headerlink" href="#personal-wiki" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I like markdown. I also like &lt;a href="https://www.notion.so/"&gt;Notion&lt;/a&gt;. I like making my own projects and tools even more.
So why not create a personal wiki to document my notes and links? I'm not &lt;em&gt;entirely&lt;/em&gt; sure how to use it &lt;em&gt;properly&lt;/em&gt; just yet, but I'll get there.&lt;/p&gt;
&lt;p&gt;To not limit myself to set taxonomies&lt;sup id="fnref:2-1"&gt;&lt;a class="footnote-ref" href="#fn:2-1"&gt;1&lt;/a&gt;&lt;/sup&gt; I thought of something called &lt;em&gt;link&lt;/em&gt; - essentially a relationshop of a document.
This way, if a document is related to a project called Saisho, I'd use [&lt;code&gt;[link]] project:saisho&lt;/code&gt;, if it's related to a category called recipes, I'd use &lt;code&gt;category:recipes&lt;/code&gt; or if it's related to another document I'd use &lt;code&gt;page:another-page&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Personal Wiki" src="https://0xff.nu/i/firefox_piV4w6d3wY-fs8.png" /&gt;&lt;/p&gt;
&lt;p&gt;There is still &lt;strong&gt;lots&lt;/strong&gt; to be done (tags only &lt;em&gt;just&lt;/em&gt; exist, lots of optimization, search etc) to make my personal wiki into something I'd even consider releasing to the general public, but this is the best way to do it - use your own tools.&lt;/p&gt;
&lt;h2 id="and-does-it-work"&gt;And.. does it work?&lt;a class="headerlink" href="#and-does-it-work" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Tools are just half the story. The real challenge is to keep at it and find a comfortable workflow so that organization is not a hassle, but an aid.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:2-1"&gt;
&lt;p&gt;A taxonomy within WordPress is a way of grouping posts together based on a select number of relationships.&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><pubDate>Fri, 12 Jun 2020 00:00:00 -0000</pubDate></item><item><title>The quest for a job in 2020</title><link>https://0xff.nu/job-search/</link><description>&lt;p&gt;Some of you may know that I was recently fired. While I'm not going to go into too much detail, I'll say that it
was due to COVID-19 related cutbacks or related reasons (at least according to my former boss).&lt;/p&gt;
&lt;p&gt;As this is still an ongoing adventure, there is not much I can write about just yet. That being said, a few notes:
- Nobody is ever immune to being thrown to the wolves. I honestly did not expect to get fired, especially considering my former boss knew I'm a new father.
- Certain workplaces don't like honesty and would prefer you to cover the truth just so it looks good.
- Israeli companies like being unprofessional. Lowballing you after agreeing to your salary expectation and saying they loved you is a thing.
- Looking for a job during an ongoing epidemic &lt;del&gt;could be&lt;/del&gt; is an excercise in frustration.
- Keep your mind sharp between jobs. This is how I came up with &lt;a href="https://paulglushak.com/saisho"&gt;Saisho&lt;/a&gt; and &lt;a href="https://paulglushak.com/shigoto"&gt;Shigoto&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Fri, 12 Jun 2020 00:00:00 -0000</pubDate></item><item><title>Hinode</title><link>https://0xff.nu/bludit-hinode/</link><description>&lt;p&gt;&lt;img alt="Hinode Logo" src="https://paulglushak.com/bl-content/uploads/pages/e9c3f84dae748af84900b43164216fb7/Flag-hinode.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;日の出&lt;/strong&gt; (&lt;em&gt;Hinode&lt;/em&gt;) is a clean, minimal and bright theme for Bludit.&lt;/p&gt;
&lt;p&gt;It started it's life as a commission which fell through, so I've decided to share it with everyone.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Since this was supposed to be a paid commission, if you like the theme, please consider &lt;a href="https://ko-fi.com/hxii_"&gt;donating/tipping&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="download"&gt;Download&lt;a class="headerlink" href="#download" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can download Hinode from &lt;a href="https://git.sr.ht/~hxii/hinode"&gt;Sourcehut&lt;/a&gt; or &lt;a href="https://github.com/hxii/hinode"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="screenshots"&gt;Screenshots&lt;a class="headerlink" href="#screenshots" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img alt="Image description" src="https://paulglushak.com/bl-content/uploads/pages/e9c3f84dae748af84900b43164216fb7/hinode-1.jpg" /&gt;
&lt;img alt="Image description" src="https://paulglushak.com/bl-content/uploads/pages/e9c3f84dae748af84900b43164216fb7/hinode-2.jpg" /&gt;
&lt;img alt="Image description" src="https://paulglushak.com/bl-content/uploads/pages/e9c3f84dae748af84900b43164216fb7/hinode-3.jpg" /&gt;&lt;/p&gt;</description><pubDate>Sat, 30 May 2020 00:00:00 -0000</pubDate></item><item><title>Shigoto</title><link>https://0xff.nu/shigoto/</link><description>&lt;p&gt;&lt;img alt="Shigoto Logo" src="https://paulglushak.com/flag-shigoto.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Shigoto&lt;/em&gt; is a minimalistic &lt;a href="http://todotxt.org/"&gt;todo.txt&lt;/a&gt; parser and manager. It was created as a personal tool to try and get used to organizing tasks properly in a bloat-free manner.&lt;/p&gt;
&lt;h2 id="what-it-doesnt-have"&gt;What it doesn't have&lt;a class="headerlink" href="#what-it-doesnt-have" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Sorting is currently broken.&lt;/li&gt;
&lt;li&gt;Code is most likely not optimized.&lt;/li&gt;
&lt;li&gt;Not ready for mobile yet.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Something else? &lt;a href="https://todo.sr.ht/~hxii/shigoto"&gt;let me know&lt;/a&gt;!&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="what-it-has"&gt;What it has&lt;a class="headerlink" href="#what-it-has" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Reads and parses todo.txt.&lt;/li&gt;
&lt;li&gt;Filtering based on project, context and priority.&lt;/li&gt;
&lt;li&gt;Archiving (done.txt) and marking as done.&lt;/li&gt;
&lt;li&gt;Password protected. (TBD)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="usage"&gt;Usage&lt;a class="headerlink" href="#usage" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Set hashed password in &lt;code&gt;config.php&lt;/code&gt; using &lt;del&gt;BCrypt&lt;/del&gt; argon2id (HMAC of password with pepper set in &lt;code&gt;pep.php&lt;/code&gt;; see below).&lt;/li&gt;
&lt;li&gt;Copy and paste your &lt;code&gt;todo.txt&lt;/code&gt; file in the same folder as Shigoto. (if you don't have one, an empty file will be created)&lt;/li&gt;
&lt;li&gt;Added September 15th, 2020: create a file called &lt;code&gt;pep.php&lt;/code&gt; where you will store your password pepper (or change the file and it's location in &lt;code&gt;login.php:5&lt;/code&gt;) that looks like this:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class="language-PHP"&gt;&amp;lt;?php

defined('SHIGOTO') or die();

return 'your-sha256-pepper-here';
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="notes"&gt;Notes&lt;a class="headerlink" href="#notes" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;This was created as a personal project, so basically everything is an afterthought.&lt;/li&gt;
&lt;li&gt;This is supposed to be minimalistic, but I tried covering the basics. If you think something basic is missing, let me know!&lt;/li&gt;
&lt;li&gt;This code in this project is far from ideal, but I'm getting better.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="download"&gt;Download&lt;a class="headerlink" href="#download" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Get it on &lt;a href="https://git.sr.ht/~hxii/shigoto"&gt;Sourcehut&lt;/a&gt; or &lt;a href="https://github.com/hxii/shigoto"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Like it? Consider a small &lt;strong&gt;&lt;a href="https://ko-fi.com/hxii_"&gt;donation&lt;/a&gt;&lt;/strong&gt;, it's very much appreciated!&lt;/p&gt;</description><pubDate>Sat, 30 May 2020 00:00:00 -0000</pubDate></item><item><title>Why saisho?🤔</title><link>https://0xff.nu/why-saisho/</link><description>&lt;p&gt;Why did I make &lt;em&gt;Saisho&lt;/em&gt;? To be honest with you, I didn't think I was going to use it. In a sense, at least that's what I thought initially, &lt;em&gt;Saisho&lt;/em&gt; was &lt;strong&gt;too&lt;/strong&gt; minimal.&lt;/p&gt;
&lt;p&gt;I wasn't sure I was ready to give up on a GUI to edit the content of my blog/website/whatever. It's comfortable.&lt;/p&gt;
&lt;p&gt;Thing is, we humans have a very good ability - we adapt. Saisho was a challenge to myself - get out of this comfort zone and create something that, I myself, will use. Bonus points if others will too.&lt;/p&gt;
&lt;p&gt;The starting point was perfection&lt;sup id="fnref:2-1"&gt;&lt;a class="footnote-ref" href="#fn:2-1"&gt;1&lt;/a&gt;&lt;/sup&gt; to which I will only add the things that matter, no bells, no whistles.&lt;/p&gt;
&lt;p&gt;I believe I have managed to achieve that (albeit with messy code) - &lt;em&gt;Saisho&lt;/em&gt; takes &lt;abbr title="MarkDown"&gt;MD&lt;/abbr&gt; files (with some extra metadata&lt;sup id="fnref:2-2"&gt;&lt;a class="footnote-ref" href="#fn:2-2"&gt;2&lt;/a&gt;&lt;/sup&gt;), parses them and saves a cached &lt;abbr title="HyperText Markup Language"&gt;HTML&lt;/abbr&gt; file to be served. Now there's also an &lt;abbr title="Rich Site Summary"&gt;RSS&lt;/abbr&gt; feed thrown in.&lt;/p&gt;
&lt;p&gt;That's it.&lt;/p&gt;
&lt;p&gt;And while my code is a mess and template support could be done much better, I don't think &lt;em&gt;Saisho&lt;/em&gt; &lt;strong&gt;needs&lt;/strong&gt; any extra features besides this.&lt;/p&gt;
&lt;p&gt;Features are there to answer a need or solve a problem. If a feature does neither, we don't really need it.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:2-1"&gt;
&lt;p&gt;“Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.” -- Antoine de Saint-Exupéry, Airman's Odyssey&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2-2"&gt;
&lt;p&gt;The basics are title, date and description but Saisho will parse any &lt;code&gt;[[metadata]]&lt;/code&gt;.&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-2" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><pubDate>Sat, 23 May 2020 00:00:00 -0000</pubDate></item><item><title>Muji?</title><link>https://0xff.nu/muji/</link><description>&lt;p&gt;This is a new template for &lt;a href="https://git.sr.ht/~hxii/saisho"&gt;Saisho&lt;/a&gt; called &lt;em&gt;Muji&lt;/em&gt; (temporary name).
You can now see it in action on this website (0xFF.nu).&lt;/p&gt;
&lt;p&gt;It was built, again, with barren simplicity in mind. But look how readable!&lt;/p&gt;</description><pubDate>Thu, 21 May 2020 00:00:00 -0000</pubDate></item><item><title>Overkill Compliance</title><link>https://0xff.nu/overkill-compliance/</link><description>&lt;p&gt;A little while ago, I wrote a very simple and small WordPress plugin&lt;sup id="fnref:2-1"&gt;&lt;a class="footnote-ref" href="#fn:2-1"&gt;1&lt;/a&gt;&lt;/sup&gt; (we're talking 1597 bytes of actual code, or 1128 bytes if we were to remove CSS) that answered a very specific requirement.
One which does not (to the best of my knowledge) exist in WordPress&lt;sup id="fnref:2-2"&gt;&lt;a class="footnote-ref" href="#fn:2-2"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Due to the fact the project in which the plugin was supposed to be used for never came to light and after making sure it works (as well as adding some functionality), I've decided to upload it to WordPress.org thinking others may find use in it.
Having submitted two plugins to WordPress.org in the past and not encountering issues in the submission/validation process, I never expected to receive the reply I received.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;At this time, we are not accepting plugins of this nature.&lt;/p&gt;
&lt;p&gt;Plugins that reproduce features that are already included in WordPress, without any perceivable additions, such as (but not limited to) duplication of existing short codes ([embed] and [gallery]), widgets (rss feed display), or functionality (adding users), will not be accepted.&lt;/p&gt;
&lt;p&gt;In your specific case, there's no need for a shortcode to embed WordPress posts because WordPress auto-embeds posts. Just paste the URL of the post you want to embed on it's own line (or in it's own block) and it will automatically do that for you.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This was the content of the validation email I've received from WordPress.org. Needless to say, I did not agree with their decision.&lt;/p&gt;
&lt;p&gt;I sent a reply explaining that the built-in functionality differs (including a screenshot!) from the one my plugin offers.
I was met with the following reply:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You do not need any plugin to do this, WordPress now does this by default and built-in.
Literally, you're recreating built in functionality. Just paste a link to a WordPress post on its own line, or use the embed block, and it just works. No need for any plugin at all.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I thought maybe I'm not conveying my point clearly, so I sent another screenshot explaining the difference in functionality. This was met with the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There are a few critical flaws in your approach. First, and most importantly here, you're using shortcodes. It's about to be 2020 and all new sites default to Gutenberg. Having an insert require shortcodes today is short sighted, especially because of the second flaw. You're requiring people to know the post ID.
But also you totally missed https://wordpress.org/plugins/posts-in-page/
If you wanted to make a full blown Gutenberg-ized version, that would be one thing. But you haven't actually created anything new here. It's absolutely useful, yes, but it already exists both in the plugin you found and posts-in-page.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The problem, then, is NOT in the "existing" functionality, but rather forcing plugin creators to use Gutenberg&lt;sup id="fnref:2-3"&gt;&lt;a class="footnote-ref" href="#fn:2-3"&gt;3&lt;/a&gt;&lt;/sup&gt; (with it's thousands&lt;sup id="fnref:2-4"&gt;&lt;a class="footnote-ref" href="#fn:2-4"&gt;4&lt;/a&gt;&lt;/sup&gt; of bugs) instead of creating a lightweight, simple plugin (I'm leaving the fact that both the plugin that I found, and the one they sent over are VERY outdated).&lt;/p&gt;
&lt;p&gt;You're strong-arming me (and others) to introduce more than the required amount into something so simple in order to be "compliant". Overkill, just like the rest of the platform.&lt;/p&gt;
&lt;p&gt;Needless to say, I gave up on submitting this plugin. Whoever needs this functionality, will hopefully find my repo.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:2-1"&gt;
&lt;p&gt;Embed Post, available on &lt;a href="https://github.com/hxii/embed_post"&gt;GitHub&lt;/a&gt;.&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2-2"&gt;
&lt;p&gt;The plugin allows a user to seamlessly embed a post in a different post, in order to avoid content duplication. Was created to be used with knowledgebases where bits and pieces are often referenced by different articles.&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-2" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2-3"&gt;
&lt;p&gt;Gutenberg is the new wordpress post editor: https://wordpress.org/gutenberg/&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-3" title="Jump back to footnote 3 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2-4"&gt;
&lt;p&gt;https://github.com/WordPress/gutenberg/issues&amp;#160;&lt;a class="footnote-backref" href="#fnref:2-4" title="Jump back to footnote 4 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description><pubDate>Fri, 15 May 2020 00:00:00 -0000</pubDate></item><item><title>Pursuing Minimalism</title><link>https://0xff.nu/pursuing-minimalism/</link><description>&lt;p&gt;Minimalism is a tricky subject as it's very personal - your interpretation of &lt;em&gt;minimal&lt;/em&gt; may differ from mine, as may it's execution.&lt;/p&gt;
&lt;p&gt;I've written about &lt;a href="https://paulglushak.com/minimalism-in-design"&gt;minimalism in (web)design&lt;/a&gt; before but seeing as I, in a sense, deviated from my own preaching a bit, I've decided to write an addendum.&lt;/p&gt;
&lt;p&gt;While I still try and be as minimalist as possible in my approach, stylistic value still has some importance so my &lt;a href="https://paulglushak.com"&gt;main website&lt;/a&gt; (I have no idea WHY I have more than one website yet, we'll see) DID end up using a webfont, or more specifically &lt;a href="https://rsms.me/inter/"&gt;Inter&lt;/a&gt;. Mostly because font rendering in Windows is absolutely atrocious and all fonts &lt;code&gt;sans-serif&lt;/code&gt; look like ass.&lt;/p&gt;
&lt;p&gt;That being said, the irony is not lost on me. While my website, at least currently, does use a webfont and has some basic animations as creature comforts, I created &lt;a href="https://paulglushak.com/u"&gt;μ&lt;/a&gt; (and later &lt;a href="https://cv.glushak.net/"&gt;u.2&lt;/a&gt;) without these things.
You can actually see μ in action here, except this websites uses another creation of mine - &lt;a href="https://paulglushak.com/saisho"&gt;Saisho&lt;/a&gt; which is a very basic website engine.&lt;/p&gt;
&lt;p&gt;There is currently nothing that is extra, everything is functional and (most likely) as small as it can be.&lt;/p&gt;
&lt;p&gt;While my approach may not be minimal to you, it is to me, considering my starting line was WordPress with downloaded themes, and here I am, using a custom made theme, on a custom made engine, writing my thoughts through using a terminal to a server, watching my words become static HTML files.&lt;/p&gt;
&lt;p&gt;No more noise.&lt;/p&gt;</description><pubDate>Thu, 14 May 2020 00:00:00 -0000</pubDate></item><item><title>Saisho</title><link>https://0xff.nu/saisho/</link><description>&lt;p&gt;&lt;em&gt;Saishō&lt;/em&gt; is a very simple and quick semi-static website "generator" built in PHP.&lt;/p&gt;
&lt;p&gt;It was created as a fun experiment to be used with personal projects.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://git.sr.ht/~hxii/saisho"&gt;Get via Sourcehut&lt;/a&gt;, &lt;a href="https://sho.glushak.net"&gt;Demo&lt;/a&gt;, &lt;a href="https://todo.sr.ht/~hxii/saisho"&gt;Bugs&lt;/a&gt;&lt;/p&gt;</description><pubDate>Tue, 12 May 2020 00:00:00 -0000</pubDate></item><item><title>Micro</title><link>https://0xff.nu/bludit-micro/</link><description>&lt;p&gt;&lt;em&gt;Micro (μ)&lt;/em&gt; is a minimalist, responsive theme for &lt;a href="https://www.bludit.com/"&gt;Bludit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Made for those people that want to cut out the noise and focus on the important part - the content.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1 file for Home and Pages.&lt;/li&gt;
&lt;li&gt;Categories are mentioned but are not used.&lt;/li&gt;
&lt;li&gt;Tags are not used.&lt;/li&gt;
&lt;li&gt;666 bytes of CSS.&lt;/li&gt;
&lt;li&gt;HTML only with &lt;code&gt;?textonly&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Responsive.&lt;/li&gt;
&lt;li&gt;Dark mode.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://dev.glushak.net/"&gt;Demo&lt;/a&gt;
&lt;a href="http://u2.glushak.net/"&gt;Iteration 2 Demo (μ.2)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gum.co/SwSGwl"&gt;Support via Gumroad&lt;/a&gt;
&lt;a href="https://github.com/hxii/u"&gt;Download @ GitHub&lt;/a&gt;&lt;/p&gt;</description><pubDate>Mon, 04 May 2020 00:00:00 -0000</pubDate></item><item><title>Motherfucking Websites</title><link>https://0xff.nu/motherfucking-websites/</link><description>&lt;p&gt;&lt;a href="https://justinjackson.ca/words.html"&gt;This is a webpage&lt;/a&gt; is probably the cause of all of these.
&lt;a href="https://motherfuckingwebsite.com/"&gt;Motherfuckingwebsite&lt;/a&gt; is the original.
&lt;a href="http://bettermotherfuckingwebsite.com/"&gt;Bettermotherfuckingwebsite&lt;/a&gt; introduces minimal styling and already looks better (&lt;a href="https://securemotherfuckingwebsite.com/"&gt;secure&lt;/a&gt; version as well).
The stylistic choices of both &lt;a href="https://perfectmotherfuckingwebsite.com/"&gt;Perfectmotherfuckingwebsite&lt;/a&gt; and &lt;a href="https://evenbettermotherfucking.website/"&gt;Evenbettermotherfuckingwebsite&lt;/a&gt; are different, but both are iterations of the previous two (whether they are &lt;em&gt;improvements&lt;/em&gt; are up to you).&lt;/p&gt;
&lt;p&gt;Know of any more? I'll add them.&lt;/p&gt;</description><pubDate>Fri, 01 May 2020 00:00:00 -0000</pubDate></item><item><title>Job Application Pseudo-code Questions</title><link>https://0xff.nu/job-pseudo-code-questions/</link><description>&lt;p&gt;Part of my job as a support engineer (Tier 3 Support, whatever that means.. advanced support, in short) includes coming up with things.
Now, some of those things are meant to make someone's life easier and some are there to low-key torment you. I learned something and decided to share this with you.&lt;/p&gt;
&lt;p&gt;I've been asked to re-design and update a job interview exam to be more challenging and to evaluate the analytical skill of our candidates.
Having been through similar questions myself, I've decided to include some pseudo-code challenges.&lt;/p&gt;
&lt;p&gt;Personally, I never had to write pseudo-code before (in any capacity), so this was a learning curve for me as well. How do I go about presenting an idea or process in an understandable, yet undisclosing, manner? After all, I want &lt;strong&gt;you&lt;/strong&gt; to explain to me what this fucking nonsense does, not the other way around.
We've decided on two challenges: a reading excercise and a writing one.&lt;/p&gt;
&lt;p&gt;If you'd like, you can give these a go and let me know what you think by &lt;a href="&amp;#109;&amp;#97;&amp;#105;&amp;#108;&amp;#116;&amp;#111;&amp;#58;&amp;#112;&amp;#97;&amp;#117;&amp;#108;&amp;#64;&amp;#103;&amp;#108;&amp;#117;&amp;#115;&amp;#104;&amp;#97;&amp;#107;&amp;#46;&amp;#110;&amp;#101;&amp;#116;"&gt;email&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="reading"&gt;Reading&lt;a class="headerlink" href="#reading" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The point here is for the applicant to try and understand what the code block does and what is the expected output. This is more of an excercise in logic rather than programming knowledge (although it is very beneficial if you've seen/used code before). I want to see if and how you will handle something you don't know without running for the hills (and we've had candidates just leaving).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var lib = [
    'bk3725' =&amp;gt; 'Five Shades of White',
    'bk3476' =&amp;gt; 'Larry Plotter and the Engineer\'s Pebble',
    'bk3281' =&amp;gt; 'The Snitcher',
    'bk4897' =&amp;gt; 'The Stitchmaker\'s Guide to the Galaxy 10'
]
sort(lib)
print('Books available')
foreach lib as book =&amp;gt; name
  if ( replace('bk', '', book) &amp;lt;= 3500 and substring(book, -1) != 7 )
    unset(lib[book])
  end if
  print(name + ' (' + book + ')')
end foreach
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, I personally use PHP and some Ruby, so maybe that is the reason the abomination above looks like it does. I apologise.&lt;/p&gt;
&lt;h2 id="writing"&gt;Writing&lt;a class="headerlink" href="#writing" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since you're still here, you probably understand pseudo-code or can at least make sense of it. Good.
For the second task I've decided to introduce a bit more complexity, so I actually went ahead and solved it myself in PHP first and only then adjusted the "syntax" to pseudo-code to make sure this can be answered.&lt;/p&gt;
&lt;p&gt;Here we were asking the candidate to write a simple savings calculator where the input is:
- The initial deposit
- Monthly contribution
- Annual interest rate
- Duration of savings account
The output should be the account total, total interest and total contribution.&lt;/p&gt;
&lt;p&gt;This question requires mostly logic and a basic knowledge of how programming works (in any language, really).&lt;/p&gt;
&lt;h2 id="results"&gt;Results&lt;a class="headerlink" href="#results" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The point was never to make something hard or unsolvable. I've actually verified that the whole exam (5 questions in total), including the two questions above, can be resolved within the time limit.
We have had people with adequate experience (according to their CVs) leaving the interview with no questions answered, which is less then fucking ideal.&lt;/p&gt;
&lt;p&gt;That being said, I am still gathering feedback. After all, this is valuable experience and knowledge for me as well.&lt;/p&gt;</description><pubDate>Sun, 16 Feb 2020 00:00:00 -0000</pubDate></item><item><title>Ultra Clean</title><link>https://0xff.nu/ultra-clean/</link><description>&lt;p&gt;&lt;a href="https://paulglushak.com/bludit-boilerplate/"&gt;Bludit Boilerplate&lt;/a&gt; is nice, but what if I'm &lt;strong&gt;real&lt;/strong&gt; fucking lazy?&lt;/p&gt;
&lt;p&gt;No worries, here's a simple sample CSS (in addition to what's already in BLBP) to make BLBP look like this:
&lt;img alt="Sexy minimalist design" src="https://paulglushak.com/bl-content/uploads/pages/30d590625ca2a79b2cbb7c2d678ba19f/ScreenShot2020-01-16at3.06.27PM.png" /&gt;&lt;span class="caption"&gt;Sexy, sexy minimalism.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="button" href="https://paypal.me/PaulGlushak"&gt;Support Me&lt;/a&gt;
&lt;a class="button" href="https://ko-fi.com/hxii__"&gt;Buy me a {beverage} on ko-fi&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here's the CSS, free of charge:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-CSS"&gt;html {
    font-size: 15px;
}
body {
    font-family:-apple-system,BlinkMacSystemFont,&amp;quot;Segoe UI&amp;quot;,Roboto,Helvetica,Arial,sans-serif,&amp;quot;Apple Color Emoji&amp;quot;,&amp;quot;Segoe UI Emoji&amp;quot;,&amp;quot;Segoe UI Symbol&amp;quot;;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
    font-size: 1rem;
    line-height: 1.6;
    margin: 2rem;
    background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAPElEQVRIS+3SIRIAMAjEwPD/RxdVHYVL9U1hlhvgAcPRO/v479sAvVxEEamABmpRRCqggVoUkQpo4LxFC49HARl6Ae7nAAAAAElFTkSuQmCC) repeat;
}
.container {
    max-width: 600px;
    background: #fff;
}
header .content {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
}
header hr {
    display: none;
}
.logo h2 {
    font-size: inherit;
    display: inline-block;
}
.slogan {
    display: none;
}
ul.nav, ul.tags {
    display: flex;
    flex-direction: row;
    margin: 0;
    padding: 0;
    list-style-type: none;
}
ul.nav li + li {
    margin-left: 1rem;
}
.article-list {
    margin: 1rem 0;
}
article.list-article {
    display: flex;
    justify-content: space-between;
}
.list-article .article-name span {
    display: none;
}
ul.tags li + li {
    margin-left: 1rem;
}
footer .plugin {
    margin-bottom: 2rem;
}
a, a:visited {
    color: #000;
}
a:hover {
    color: #1a41ff;
}
hr {
    margin: 2rem 0;
}
@media screen and (max-width: 640px) {
    body {
        margin: 1rem;
    }
}
&lt;/code&gt;&lt;/pre&gt;</description><pubDate>Thu, 16 Jan 2020 00:00:00 -0000</pubDate></item><item><title>Bludit Boilerplate</title><link>https://0xff.nu/bludit-boilerplate/</link><description>&lt;p&gt;Bludit Boilerplate. No Bullshit. Build YOUR OWN theme.&lt;/p&gt;
&lt;p&gt;This is &lt;strong&gt;not&lt;/strong&gt; a theme (although it can be used as is).
This is, however, a &lt;strong&gt;starting point&lt;/strong&gt; for &lt;strong&gt;your&lt;/strong&gt; theme.&lt;/p&gt;
&lt;p&gt;&lt;a class="button" href="https://github.com/hxii/bludit-boilerplate"&gt;Get on GitHub&lt;/a&gt;
&lt;a class="button" href="https://paypal.me/PaulGlushak"&gt;Support Me&lt;/a&gt;
&lt;a class="button" href="https://ko-fi.com/hxii__"&gt;Buy me a {beverage} on ko-fi&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="whats-included"&gt;Whats included?&lt;a class="headerlink" href="#whats-included" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Theme boilerplate with pages, tags and categories.&lt;/li&gt;
&lt;li&gt;217B (that's bytes) of CSS that you don't have to include. Purely for basic aesthetic reasons.&lt;/li&gt;
&lt;li&gt;Support for templates. If you set a template in bludit, the theme will try to include &lt;code&gt;inc/{template-name}.php&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Support for &lt;em&gt;important&lt;/em&gt; posts. All you have to do is implement a custom &lt;code&gt;bool&lt;/code&gt; for important in your Custom Fields i.e.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;{
    &amp;quot;important&amp;quot;: {
        &amp;quot;type&amp;quot;: &amp;quot;bool&amp;quot;,
        &amp;quot;label&amp;quot;: &amp;quot;Important&amp;quot;,
        &amp;quot;tip&amp;quot;: &amp;quot;Is this an important article?&amp;quot;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="installation"&gt;Installation&lt;a class="headerlink" href="#installation" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Download BLBP and extract to your &lt;code&gt;bl-themes&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;Change &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt; in &lt;code&gt;en.json&lt;/code&gt; to your theme's name.&lt;/li&gt;
&lt;li&gt;Make changes and design YOUR theme.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="credit"&gt;Credit&lt;a class="headerlink" href="#credit" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I would much appreciate if you leave credit if you use this boilerplate and find it useful.&lt;/p&gt;
&lt;h2 id="more"&gt;More&lt;a class="headerlink" href="#more" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If there's anything you feel is broken, incorrect or if you feel like this project can be improved somehow, please open issues and/or pull-requests and I'll be glad to take a look.&lt;/p&gt;
&lt;h2 id="screenshots"&gt;Screenshots&lt;a class="headerlink" href="#screenshots" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img alt="Image description" src="https://paulglushak.com/bl-content/uploads/pages/55111c0dbecaef173ad4ba00c8b729c6/ScreenShot2020-01-14at5.20.05PM.png" /&gt;
&lt;img alt="Image description" src="https://paulglushak.com/bl-content/uploads/pages/55111c0dbecaef173ad4ba00c8b729c6/ScreenShot2020-01-14at5.19.58PM.png" /&gt;
&lt;img alt="Image description" src="https://paulglushak.com/bl-content/uploads/pages/55111c0dbecaef173ad4ba00c8b729c6/ScreenShot2020-01-14at5.19.38PM.png" /&gt;&lt;/p&gt;</description><pubDate>Tue, 14 Jan 2020 00:00:00 -0000</pubDate></item><item><title>End of Twenty Nineteen</title><link>https://0xff.nu/end-of-2019/</link><description>&lt;p&gt;Another year passed and another year begins. This is exactly the time to summarize experiences and set 'goals' for the upcoming year. This is what you'd call &lt;del&gt;new year resolutions&lt;/del&gt;.&lt;/p&gt;
&lt;p&gt;2019 was an interesting year for me for the most part. I started doing &lt;a href="https://paulglushak.com/yotpo-reviews-for-woocommerce"&gt;new things&lt;/a&gt;, got promoted (largerly, more of the same) and learned that I'm about to become a father. Quite eventful.&lt;/p&gt;
&lt;h2 id="goals"&gt;Goals&lt;a class="headerlink" href="#goals" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I don't like setting solid goals for the new year (we all know that fucking "go to the gym" goal, right?) but I do like deciding on a direction that I'd like to work towards, and so I came up with the following things I'd like to focus on in 2020:
- Learn &lt;strong&gt;how&lt;/strong&gt; to be a father. Being responsible for a living thing is fucking scary, especially when that living thing &lt;strong&gt;learns&lt;/strong&gt; from everything you do.
- Figure out what the fuck I want my next step in my career to be. I &lt;em&gt;kinda&lt;/em&gt; know what I want, but I'm still at the point where everything is interesting and I can't seem to choose what to focus on.
- Despite the fact I still believe I'm not much of a developer, I'd like to learn a new language (Ruby? Python? Something else?) and improve my knowledge of PHP. Should be good for both me and my employer.&lt;/p&gt;
&lt;h2 id="places-i-visited"&gt;Places I visited&lt;a class="headerlink" href="#places-i-visited" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here are the places I managed to visit this past year.
&lt;img alt="New York, March 2019" src="https://paulglushak.com/bl-content/uploads/pages/ec2f3c9ab4b32d4411eb2c229cc86b54/IMG_20190312_195627.jpg" /&gt;&lt;span class="caption"&gt;Times Square - New York, March 2019&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Czech Republic, August 2019" src="https://paulglushak.com/bl-content/uploads/pages/ec2f3c9ab4b32d4411eb2c229cc86b54/IMG_20190803_103025.jpg" /&gt;&lt;span class="caption"&gt;MotoGP - Czech Republic, August 2019&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Romania, September 2019" src="https://paulglushak.com/bl-content/uploads/pages/ec2f3c9ab4b32d4411eb2c229cc86b54/MVIMG_20191010_162033.jpg" /&gt;&lt;span class="caption"&gt;Transfagarsan - Romania, September 2019&lt;/span&gt;&lt;/p&gt;</description><pubDate>Thu, 02 Jan 2020 00:00:00 -0000</pubDate></item><item><title>Configure FastCGI Cache for Bludit</title><link>https://0xff.nu/configure-fastcgi-bludit/</link><description>&lt;p&gt;Following my &lt;a href="https://paulglushak.com/fastcgi-purge-for-bludit"&gt;FastCGI Cache Purge plugin for Bludit&lt;/a&gt;, I've been asked how FastCGI cache is even configured for Bludit. &lt;/p&gt;
&lt;p&gt;This is &lt;strong&gt;not&lt;/strong&gt; a beginner guide, so I assume you have nginx installed together with the &lt;code&gt;ngx_cache_purge&lt;/code&gt; module. If you don't, there are a few guides online how to build nginx from source with the module &lt;a href="https://www.digitalberg.com/WiKi/how-to-compile-nginx-plus-ngx_cache_purge-for-wordpress-on-ubuntu-centos/"&gt;like this&lt;/a&gt;. Generally configuring FastCGI cache also &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-setup-fastcgi-caching-with-nginx-on-your-vps"&gt;shouldn't be a problem&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The gist is to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Configure a cache zone.&lt;/li&gt;
&lt;li&gt;Configure Bludit specifics and&lt;/li&gt;
&lt;li&gt;Configure purge location.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="bludit-specifics"&gt;Bludit Specifics&lt;a class="headerlink" href="#bludit-specifics" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since there are things we don't want to cache, they need to be configured. I used the following settings:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# This will prevent caching anything in the admin and any POST requests.
if ($request_uri ~* &amp;quot;/admin/|/bl-kernel/&amp;quot;) {
  set $skip_cache 1;
}
if ($request_method = POST) {
  set $skip_cache 1;
}
# This will allow to use the purging plugin. Note that you need to replace YOURZONE with what you set up for FastCGI cache. 
location ~ /purge(/.*) {
  allow your.server.ip.address;
    deny all;
  fastcgi_cache_purge YOURZONE &amp;quot;$scheme$request_method$host$1&amp;quot;;
  access_log off;
}
# My website rarely changes, so all pages are cached for 48 hours.
location ~ \.php$ {
...
  fastcgi_cache_bypass $skip_cache;
  fastcgi_no_cache $skip_cache;
  fastcgi_cache YOURZONE;
  fastcgi_cache_valid 200 302 48h;
  fastcgi_cache_valid 404 1m;
}
# Unrelated to fastcgi cache, but if we're already modifying configs...
location ~*  \.(jpg|jpeg|png|gif|ico|css|js)$ {
  expires 7d;
}
location ~ /wp\S* {
  deny all;
  access_log off;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="what-do-we-gain"&gt;What do we gain?&lt;a class="headerlink" href="#what-do-we-gain" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img alt="With FastCGI Cache" src="https://paulglushak.com/bl-content/uploads/pages/autosave-dbd663bd232e9dd5c26c9aaa009405fb/ScreenShot2019-12-11at12.04.27PM.png" /&gt;&lt;span class="caption"&gt;Fig.1 With FastCGI Cache&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Without FastCGI Cache" src="https://paulglushak.com/bl-content/uploads/pages/autosave-dbd663bd232e9dd5c26c9aaa009405fb/ScreenShot2019-12-11at12.08.18PM.png" /&gt;&lt;span class="caption"&gt;Fig.2 Without FastCGI Cache&lt;/span&gt;&lt;/p&gt;</description><pubDate>Tue, 10 Dec 2019 00:00:00 -0000</pubDate></item><item><title>FastCGI Purge for Bludit</title><link>https://0xff.nu/fcgi-purge-bludit/</link><description>&lt;p&gt;This plugin uses &lt;code&gt;ngx_cache_purge&lt;/code&gt; to purge cached pages by &lt;strong&gt;GET&lt;/strong&gt;ting the modified/deleted post using the given format.&lt;/p&gt;
&lt;p&gt;This is, again, something I needed and couldn't find.
The solution? a can of beer and an hour of work.&lt;/p&gt;
&lt;p&gt;Now you can purge the modified page, the associated tags and category as well as the index page if enabled.&lt;/p&gt;
&lt;p&gt;&lt;a class="button" href="https://github.com/hxii/bludit_fcgi_purge"&gt;Available on GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="FastCGI Purge for Bludit" src="https://paulglushak.com/bl-content/uploads/pages/b69c5ac9e885f7b96700e7177e6e4cac/ScreenShot2019-12-06at12.08.37AM(2).png" /&gt;&lt;/p&gt;</description><pubDate>Fri, 06 Dec 2019 00:00:00 -0000</pubDate></item><item><title>Minimalism in Design</title><link>https://0xff.nu/minimalism-in-design/</link><description>&lt;blockquote&gt;
&lt;p&gt;This article was originally posted on my &lt;a href="https://www.linkedin.com/pulse/minimalism-design-paul-glushak/"&gt;LinkedIn page&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So I recently updated my never-ending story of a website's once more, which required me to do some soul-searching to understand what I want and what I like.&lt;/p&gt;
&lt;p&gt;My personal website, as you can see, has always been a playground of learning and discovery to me in the sense that I just couldn't decide on one damn direction to go so I kept changing it, designing, reinstalling, moving platforms and probably most importantly abandoning the entire thing once I couldn't find a direction nor share any actual projects with the world.&lt;/p&gt;
&lt;p&gt;So this time I have decided it's going to be different. I will do this one more time, and this time I'll do it properly by starting from scratch.&lt;/p&gt;
&lt;h2 id="what-do-you-really-want"&gt;What do you really want?&lt;a class="headerlink" href="#what-do-you-really-want" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One conclusion I came to is that, for better or worse, my previous unsuccessful attempts at running my own website have been filled with following design trends. "Hello, I'm X and I'm a coffee-drinking user experience audio-visual engineer" sounds trendy so let's add it to my website. Sliders! Icons! 3 DIFFERENT GOOGLE FONTS!&lt;/p&gt;
&lt;p&gt;I just kept adding things without thinking too much whether I REALLY need them or like them. I copied ideas from many different websites, adjusted them to my needs and thus created iteration after iteration of an unholy abomination of a website until I had enough.&lt;/p&gt;
&lt;p&gt;After my domain was vacant for quite a bit and I was done mucking around, I decided that now that I am 30 years old it's finally time to get somewhat serious. And by somewhat serious I mean going from like 1 to 2 on a some sort of seriousness scale.&lt;/p&gt;
&lt;p&gt;What I came to realize was that I really didn't like or need graphics, flashy colors, JS libraries, massive frameworks, CMSs like WordPress, twenty different (albeit awesome) fonts and other distractions to create a place where I can share my work and some rambling about different subjects on the internet. I need my website to be functional, accessible and maybe somewhat pretty without adding things just for the sake of adding things. I want to create a place with information (whether it is useful or not is up to the reader). Not waste my time or yours.&lt;/p&gt;
&lt;p&gt;This is how I got in touch with my minimalist side.&lt;/p&gt;
&lt;h2 id="so-all-this-is-about-minimalism-then"&gt;So all this is about minimalism, then?&lt;a class="headerlink" href="#so-all-this-is-about-minimalism-then" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now, I'm not saying that all websites have to look like &lt;a href="https://motherfuckingwebsite.com/"&gt;motherfuckingwebsite&lt;/a&gt;, far from it, but I did start noticing that a lot of websites have unnecessary elements that (according to some) make them look more pretty but hurt readability and/or accessibility at the same time.&lt;/p&gt;
&lt;p&gt;We all know those websites with horizontal scrolling, unnecessary parallax or sliders, terrible navigation, bad contrast, overly large images and so on. I, personally, do not want to jump through hoops in order to get to the point.&lt;/p&gt;
&lt;p&gt;I wanted to find an example and boy did I find one - a poorly designed website with no less than three menus, large images, animations and other 'features' caused my MacBook Pro to overheat by utilizing way too much GPU resources for just one tab.&lt;/p&gt;
&lt;p&gt;Your design needs to complement the content, not distract from it and it doesn't matter what I'm looking at: a personal blog, a portfolio or an e-commerce store.&lt;/p&gt;
&lt;h2 id="get-to-the-point-already"&gt;Get to the point already!&lt;a class="headerlink" href="#get-to-the-point-already" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Pay attention to what you use to accomplish a task - you don't want overkill. Be it the platform of choice, graphics, frameworks, libraries and so on.&lt;/p&gt;
&lt;p&gt;Optimize. Do you really need 20 different analytics platforms? webfonts? 40 megapixel images? overkill frameworks and libraries?&lt;/p&gt;
&lt;p&gt;Be mindful. Not everyone has a fiber connection at home or even broadband for that matter. Not everyone can (or should, for that matter) download 8Mb of trash to read an article.&lt;/p&gt;
&lt;p&gt;By keeping this in mind, for example, &lt;a href="https://paulglushak.com/tidal-360-reality-audio"&gt;this article&lt;/a&gt; loads in 120ms and the whole thing weighs just 5.3Kb. The &lt;a href="https://paulglushak.com/tidal-360-reality-audio?textonly"&gt;no-CSS version&lt;/a&gt; loads in just 93ms and weighs 3.1Kb.&lt;/p&gt;
&lt;p&gt;My website can run on a potato, can yours?&lt;/p&gt;</description><pubDate>Mon, 02 Dec 2019 00:00:00 -0000</pubDate></item><item><title>Tidal 360 Reality Audio</title><link>https://0xff.nu/tidal-360/</link><description>&lt;p&gt;After updating the Sony Headphones app on my phone that is responsible for the bells and whistles of my WH-1000 XM3 headphones, I've noticed a new feature called &lt;em&gt;360 Reality Audio Setup&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I've decided to check it out and give it a shot.&lt;/p&gt;
&lt;p&gt;Hoping to get some sort of mind blowing experience, I did the thing - I took a photo of my ears through the Sony app for some clickfarm to analyze my acoustic capabilities and give me that sweet sweet IN YOUR FACE music experience.
I connected whatever the result was to Tidal, signed up for a trial of their HiFi plan (normally $20/month), checked my settings a turned blasted the 360 RA playlist full-volume.&lt;/p&gt;
&lt;p&gt;What did I learn?
- The 360RA music selection is abysmally small.
- Most of the tracks are VERY quiet and despite the noise cancelling capabilities of my headphones, I wasn't able to really enjoy the music.
- The quality, while good, did not WOW my face off. There's little to no difference between whatever 360RA really does and a good quality FLAC file.&lt;/p&gt;
&lt;p&gt;TL;DR
Interesting, but not worth my hard earned $20. I'll stick with Spotify for the time being.&lt;/p&gt;</description><pubDate>Sun, 03 Nov 2019 00:00:00 -0000</pubDate></item><item><title>Embed Post</title><link>https://0xff.nu/embed-post/</link><description>&lt;p&gt;This simple, tiny, plugin was born out of necessity and will allow you to embed posts in other posts in WordPress.
&lt;strong&gt;Not&lt;/strong&gt; available on wordpress.org, &lt;a href="/overkill-compliance"&gt;read why&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Two arguments are available:
- &lt;code&gt;post_id&lt;/code&gt; - Specifies the ID of the post to embed. Loop at your own risk.
- &lt;code&gt;class&lt;/code&gt; - Specify a custom CSS class for each embed.
&lt;br&gt;Style as &lt;code&gt;.embed_post.&amp;lt;yourclassname&amp;gt;&lt;/code&gt; and &lt;code&gt;.embed_post.&amp;lt;yourclassname&amp;gt; .embed_meta&lt;/code&gt;.&lt;br&gt;Two classes are built-in: &lt;code&gt;default&lt;/code&gt; and &lt;code&gt;seamless&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a class="button" href="https://github.com/hxii/embed_post"&gt;Get on GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading=lazy src="https://paulglushak.com/bl-content/uploads/pages/13457dabae02e7dbad1397f437b56198/embed(2).png" alt="Yo dawg" style="max-width:560px"&gt;&lt;/p&gt;</description><pubDate>Tue, 24 Sep 2019 00:00:00 -0000</pubDate></item><item><title>Shortcodes for Yotpo 1.2.0</title><link>https://0xff.nu/shortcodes-for-yotpo-120/</link><description>&lt;p&gt;In case you are using &lt;a href="https://paulglushak.com/yotpo-reviews-for-woocommerce"&gt;Yotpo Reviews for WooCommerce&lt;/a&gt; (a.k.a version 2), you have &lt;em&gt;probably&lt;/em&gt; noticed that Shortcodes for Yotpo no longer work.&lt;/p&gt;
&lt;p&gt;I have good news for you! You can download the updated code from GitHub.&lt;/p&gt;
&lt;p&gt;&lt;a class="button" href="https://github.com/hxii/shortcodes-for-yotpo/tree/1.2.0"&gt;See on GitHub&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id="i-got-here-from-the-notification-in-my-wordpress-website"&gt;I got here from the notification in my WordPress website!&lt;a class="headerlink" href="#i-got-here-from-the-notification-in-my-wordpress-website" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First - glad you've noticed it! I figured that out of courtesy I'll push an interim update to not surprise anyone with &lt;em&gt;Shortcodes for Yotpo&lt;/em&gt; suddenly not working because the required plugin is not installed.&lt;/p&gt;
&lt;p&gt;In two words - all you have to do is install &lt;a href="https://wordpress.org/plugins/yotpo-reviews-for-woocommerce/"&gt;Yotpo Reviews for WooCommerce&lt;/a&gt; instead of &lt;a href="https://wordpress.org/plugins/yotpo-social-reviews-for-woocommerce/"&gt;Yotpo: Product &amp;amp; Photo Reviews for WooCommerce&lt;/a&gt;, configure it and then the new version of &lt;em&gt;Shortcodes for Yotpo&lt;/em&gt; will work.&lt;/p&gt;
&lt;h3 id="why-are-you-doing-this"&gt;Why are you doing this?&lt;a class="headerlink" href="#why-are-you-doing-this" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As I have control over both plugins, new features and updates are much easier and quicker to publish.&lt;/p&gt;
&lt;h3 id="what-really-changed"&gt;What &lt;em&gt;really&lt;/em&gt; changed?&lt;a class="headerlink" href="#what-really-changed" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Code cleanup.&lt;/li&gt;
&lt;li&gt;Added Q&amp;amp;A widget.&lt;/li&gt;
&lt;li&gt;Added review highlights widget.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="i-have-more-questions"&gt;I have more questions!&lt;a class="headerlink" href="#i-have-more-questions" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Don't we all! Get in touch by  &lt;a href="&amp;#109;&amp;#97;&amp;#105;&amp;#108;&amp;#116;&amp;#111;&amp;#58;&amp;#112;&amp;#97;&amp;#117;&amp;#108;&amp;#64;&amp;#103;&amp;#108;&amp;#117;&amp;#115;&amp;#104;&amp;#97;&amp;#107;&amp;#46;&amp;#110;&amp;#101;&amp;#116;"&gt;email&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Sun, 01 Sep 2019 00:00:00 -0000</pubDate></item><item><title>Yotpo Reviews for WooCommerce (YRFW)</title><link>https://0xff.nu/yrfw/</link><description>&lt;h2 id="so-what-is-yrfw-exactly"&gt;So what is YRFW exactly?&lt;a class="headerlink" href="#so-what-is-yrfw-exactly" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This plugin started it's life as a collection of fixes and modifications on top of the Yotpo WooCommerce plugin. Then I've decided that the best way to learn and fix something is to make it from scratch, which is exactly what this plugin is. It is very important to note that this is STILL work in progress, and things MAY change.&lt;/p&gt;
&lt;h2 id="what-are-the-big-changesdifferences"&gt;What are the BIG changes/differences?&lt;a class="headerlink" href="#what-are-the-big-changesdifferences" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Completely rewritten code (save from the fixes already introduced prior) in OOP.&lt;/li&gt;
&lt;li&gt;New debug and admin pages.&lt;/li&gt;
&lt;li&gt;Faster/more efficient operation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a class="button" href="https://github.com/hxii/YRFW/releases"&gt;Download from GitHub&lt;/a&gt;
&lt;a class="button" href="https://wordpress.org/plugins/yotpo-reviews-for-woocommerce/"&gt;Download from WordPress.org&lt;/a&gt;&lt;/p&gt;</description><pubDate>Sun, 18 Aug 2019 00:00:00 -0000</pubDate></item><item><title>Shortcodes for Yotpo</title><link>https://0xff.nu/shortcodes-for-yotpo/</link><description>&lt;p&gt;Want to use Yotpo widgets in page builders? Don't want to make changes to your templates?
Shortcodes for Yotpo exists for this sole purpose.&lt;/p&gt;
&lt;p&gt;This plugin will allow you to use five shortcodes in all of your posts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;[yotpo_widget]&lt;/code&gt; - Will output the main widget.
You can optionally add a &lt;code&gt;product_id&lt;/code&gt; argument (e.g. &lt;code&gt;product_id="47"&lt;/code&gt;) to show a widget for a specific product.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[yotpo_bottomline]&lt;/code&gt; - Will output the bottomline widget.
You can optionally add a &lt;code&gt;product_id&lt;/code&gt; argument (e.g. &lt;code&gt;product_id="47"&lt;/code&gt;) to show a widget for a specific product. You can also use to &lt;code&gt;noempty&lt;/code&gt; prevent empty ratings from showing up.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[yotpo_questions]&lt;/code&gt; - Will output the Q&amp;amp;A bottomline widget.
You can optionally add a &lt;code&gt;product_id&lt;/code&gt; argument (e.g. &lt;code&gt;product_id="47"&lt;/code&gt;) to show a widget for a specific product.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[yotpo_product_gallery gallery_id="5bbb561f5ea79223a9da0e7c"]&lt;/code&gt; - Will output the gallery with the chosen ID.
All customizations are done via your Yotpo account.
You can use an optional &lt;code&gt;noproduct&lt;/code&gt; argument if the gallery is either not on a product page or you want to show a specific gallery on a product page.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[yotpo_product_reviews_carousel background_color="#22fff2" mode="most-recent" type="both" count="3"]&lt;/code&gt; - Will output a reviews carousel. Take values from your Yotpo admin page.
Has a few optional arguments:
&lt;code&gt;product_id&lt;/code&gt; - will show carousel for a product.
&lt;code&gt;review_ids&lt;/code&gt; - if mode is set to manual, use this argument to provide review IDs, similar to what you get in your Yotpo admin (e.g. &lt;code&gt;review-ids="55359479,57352049,55789410,64472373"&lt;/code&gt;)
&lt;code&gt;noproduct&lt;/code&gt; - use this argument if you want to show a carousel that is not on a product page, otherwise product_id will be appended.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[yotpo_badge]&lt;/code&gt; - Will output the badge graphic.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[yotpo_testimonials]&lt;/code&gt; - Will output the standalone testimonials widget.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[yotpo_highlighs]&lt;/code&gt; - Will output review highlights widget.
You can optionally add a &lt;code&gt;product_id&lt;/code&gt; argument (e.g. &lt;code&gt;product_id="47"&lt;/code&gt;) to show a widget for a specific product.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a class="button" href="https://wordpress.org/plugins/shortcodes-for-yotpo/"&gt;Download from WP.org&lt;/a&gt;&lt;a class="button" href="https://github.com/hxii/shortcodes-for-yotpo"&gt;See on Github&lt;/a&gt;&lt;/p&gt;</description><pubDate>Thu, 15 Aug 2019 00:00:00 -0000</pubDate></item><item><title>Hxii Logger</title><link>https://0xff.nu/logger/</link><description>&lt;p&gt;This is a very simple logger class that was written to be used with the updated &lt;a href="https://github.com/hxii/YRFW"&gt;Yotpo WooCommerce Plugin&lt;/a&gt;
It's one of those things I've decided to write as I navigate the swamp that is learning PHP.&lt;/p&gt;
&lt;h2 id="wat-do"&gt;Wat do?&lt;a class="headerlink" href="#wat-do" title="Permanent link"&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As an update from the &lt;code&gt;ytdbg&lt;/code&gt; function of the past, this logger now supports:
- Debug level support (currently only two levels implemented).
- File size control and renaming old files (kinda works?)&lt;/p&gt;
&lt;p&gt;&lt;a class="button" href="https://github.com/hxii/hxiilog"&gt;See on GitHub&lt;/a&gt;&lt;/p&gt;</description><pubDate>Mon, 08 Jul 2019 00:00:00 -0000</pubDate></item></channel></rss>