<?xml version="1.0" encoding="utf-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom"><title>Ruby Klover</title><subtitle>Website about myself and the things I care about.</subtitle><updated>2025-06-20T00:00:00Z</updated><id>https://www.bruh.ltd/</id><link rel="self" href="https://www.bruh.ltd/blog/index.xml"/><link rel="alternate" href="https://www.bruh.ltd/"/><entry><title>A nightmare scenario: private intellectual property enforcement</title><summary>Getting rid of bad laws isn't enough.</summary><updated>2025-06-20T00:00:00Z</updated><id>https://www.bruh.ltd/blog/a-nightmare-scenario-private-intellectual-property-enforcement/</id><link rel="alternate" href="https://www.bruh.ltd/blog/a-nightmare-scenario-private-intellectual-property-enforcement/"/><content type="html"><![CDATA[
                    <p>Note: I'm not a lawyer, and this is not legal advice.</p>











<hgroup>
    <h2 id="background">
        Background
    </h2>

    <a href="#background" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Background'</span>
    </a>
</hgroup>



<p>Intellectual property is broken — the idea isn't necessarily bad but
the implementation sucks. This is the opinion both I and many other
people in the online nerd circles I inhabit hold. The reasons behind
it are well known:</p>
<ul>
<li>Copyright lasts for way longer than it should — 50-70 years after
the author's death (in most parts of the world).</li>
<li>Copyright disproportionately benefits large corporations rather than
regular people.</li>
<li>Current wave of generative AI was built on the works stolen from
millions of individual creators with the express purpose of
replacing them without compensation, and AI companies were allowed
to redefine what &quot;fair use&quot; means in their favor in order to get
away with it.</li>
<li>Software patents are rife with abuse by patent trolls, serve no
practical purpose, and stifle innovation by preventing projects from
using mathematically superior algorithms.</li>
<li>Hardware patents, alongside trade secrets, stifle silicon innovation
and limit the number of CPU/GPU vendors, making them great tools for
geopolitical trade wars.</li>
<li>Firmware DRM takes away the user's autonomy over the hardware that
they bought, locks them away from choosing which software to run,
and in some cases, effectively destroys their hardware by turning it
into a useless piece of plastic if the user tries to resist.</li>
<li>DRM on creative works takes away the user's ownership over the works
that they &quot;bought&quot;, allowing the publisher to do a rugpull at any
moment and to take away the user's &quot;purchases&quot; without returning
them their money.</li>
<li>Copyright and especially DRM make it much harder to preserve works
for future generations, which corporations aren't interested in
doing themselves since it's not profitable, leading to more lost
media.</li>
</ul>
<p>A reasonable conclusion many people draw from this is &quot;maybe we should
get rid of intellectual property laws?&quot; My opinion on this is, well,
complicated. In order to understand it better, let's remind ourselves
what caused the implementation to suck in the first place.</p>











<hgroup>
    <h2 id="how-did-we-get-here-">
        How did we get here?
    </h2>

    <a href="#how-did-we-get-here-" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'How did we get here?'</span>
    </a>
</hgroup>



<p>There are 3 main reasons why intellectual property is in the state
that it is right now:</p>
<dl>
<dt>Consolidation</dt>
<dd>Most important intellectual property is owned by a few extremely
large, extremely wealthy, and extremely influential corporations
that own unimaginable numbers of assets. The operating systems most
people use are owned by Google, Microsoft, and Apple. Most of the
music is owned by Sony, Universal, and Warner Bros. Most of the
movies are owned by Disney, Paramount, and the same 3 that own most
of the music.</dd>
<dt>Incentives</dt>
<dd><p>Large corporations in the form they exist today are de facto
monarchies which have one goal — make as much money as humanly
possible, spend as little as possible, give as much of the earned
money to the CEO and as little to tax agencies. This gives them a
direct financial incentive to do things like:</p>
<ul>
<li>Make their employees work as much as possible in order to maximize
the output</li>
<li>Pay their employees as little as possible, since salaries are a
major source of expenditure</li>
<li>Prevent their employees from unionizing in order to establish a
firm top-to-bottom chain of command and eliminate as much
responsibility as possible from the upper layers</li>
<li>Own the tools (e.g. software) and the output (e.g. creative works)
of their employees in order to make them as interchangeable as
possible so they can always hire new ones if the current ones are
unsatisfied with the corporate decisions</li>
<li>Continue owning as many intellectual property assets as possible
in order to remain being hard to replace and near impossible to
effectively boycott</li>
<li>Continue getting royalties from their intellectual property for as
long as possible in order to make money without doing anything</li>
<li>Continue not letting their users truly own copies of their
employees' works in order to extract as much money as possible
from the former by making them pay more than once</li>
<li>Use their wealth and influence to align the law with their
incentives, making their business easier</li>
<li>If the law doesn't want to align in a specific country, make a
compromise there but keep doing the same as before in the
countries where it does align</li>
<li>If the law is a huge inconvenience, break it in secret, burn the
evidence, and don't get caught</li>
<li>When get caught, buy their way out of it</li>
</ul>
<p>Of course, not all of these things happen all of the time because
opposing forces exist. Once they weaken, however, cracks start to
show.</p>
</dd>
<dt>Litigative power</dt>
<dd><p>For you as an individual who isn't a billionaire, it's pretty
much impossible to win a case against a large corporation. They have
orders of magnitude more money than you, they don't have to worry
about burning out because they have armies of lawyers, and they
don't have to worry about losing everything and having their life
ruined because the greatest damage you can do to them is
negligible.</p>
<p>If you try, you'll either settle out of court or get buried in
paperwork, as they'll do their best to stretch the litigation for as
long as possible. That is if you can even sue them in the first
place — many companies nowadays include a binding arbitration clause
in their terms of service, making you settle out of court by
default. If a corporation wants you to lose, you lose.</p>
</dd>
</dl>
<p>You see where this is going, right? Removal of intellectual property
laws isn't enough on its own, as it doesn't directly address any of
the above. The incentive to extract maximum money from appropriated
works remains, and so do most of the tools large corporations have at
their disposal.</p>
<p>So my argument is: If you get rid of the bad laws but keep the
incentives, the system will eventually adapt and perpetuate the bad
practices by whatever means necessary. All you'd be doing is shuffling
cards around, trading an explicit law for an implicit one.</p>
<p>In order to drive the point home, I'd like to present a hypothetical
nightmare scenario of what'd happen if <em>all</em> you did was get rid of
intellectual property laws and highlight just how disastrous the
consequences would be.</p>











<hgroup>
    <h2 id="the-scenario">
        The scenario
    </h2>

    <a href="#the-scenario" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'The scenario'</span>
    </a>
</hgroup>



<p>United States, early future — In an unprecedented act of unanimous
support by both parties, a law has passed that'll soon eliminate all
forms of intellectual property in the US, and it'll come in effect in
only a few short months. Allied countries are considering such a law
as well.</p>
<p>Fearing huge losses in profits, major hardware manufacturers, software
producers, and art publishers swiftly form an alliance. The alliance
has a single job — figure out how to keep money going. After
struggling to coordinate for a couple months, they unearth a goldmine
of a solution, just in time before the law takes effect.</p>
<p>Since they can't rely on the government to enforce intellectual
property anymore, they resort to the only lever they have left to pull
— their terms of service. The members agree to only share their IP
with other members. In order to become a member, one must agree to
terminate their service for any user found to be in violation of a
member's IP. If a user crosses the line, all the members terminate
their service with them. If a member refuses to comply, they lose
membership.</p>
<p>In order to make such enforcement feasible, considerable effort is
poured into hardware-level DRM. Since breaking DRM is now legal, it
gets implemented at the lowest level, where it's near impossible to
crack, and starts being used for everything, even the tiniest text
files. Since patents are no longer a thing, every invention becomes a
trade secret, never shared with anyone but a select few people. Any
attempt at reverse engineering becomes a violation.</p>
<p>People are reasonably outraged. As a compromise, the duration of
&quot;copyright&quot; is shortened to a more reasonable value — 50 years after
the work's first publication. Old movies become public domain, and
people rejoice. The alliance is here to stay.</p>
<p>Time passes. More countries adopt similar laws. More companies join
the alliance.</p>
<p>More time passes. As most people have already got used to the new
order, the duration of &quot;copyright&quot; slowly gets raised back up.</p>
<p>Even more time passes.</p>
<p>The year is now 2060. You're a 40 year old Gen Alpha salary man, one
of the lucky few who has a job that pays a livable salary. You have a
big extended family, and your Millennial grandma is on life support.</p>
<p>&quot;Copyright&quot; is now perpetual. All of the knowledge in the world is
either secret or behind a paywall. If you're one of the few remaining
artists, you pay more in royalties than your parents did, as AI
systems scan your works for every potential influence. Writing about
historical events? You better pay a cut to history textbook
publishers.</p>
<p>You visit your long gone great grandparents' old house. The attic has
many of their antique belongings, including a cartridge with a video
game for an almost 80 year old console. A game that can't be bought
anymore due to the licensing issues that occurred before you were even
born. You bring that cartridge home, dump it, and decide to play it in
an emulator.</p>
<p>The moment you hit play, the company that inherited the rights to the
video game discovers your actions. You lose all of your accounts, lose
your job, and they pull the plug on your grandma's life support. Your
grandma is dead, and you're next.</p>











<hgroup>
    <h2 id="conclusion">
        Conclusion
    </h2>

    <a href="#conclusion" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Conclusion'</span>
    </a>
</hgroup>



<p>Will this actually happen? Probably not. But I hope it illustrates my
point — you need to address the reasons why intellectual property is
bad first and foremost. This implies stopping companies from being
irreplaceable monstrosities, putting their ownership and control in
the hands of their employees, and making it realistic to go court
against them. Removing intellectual property laws is secondary.</p>











<hgroup>
    <h2 id="credits">
        Credits
    </h2>

    <a href="#credits" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Credits'</span>
    </a>
</hgroup>



<p>The idea of AI systems scanning your works for influences was
suggested by Juniper Stone on Discord while we were discussing this
topic.</p>

                ]]></content></entry><entry><title>Go templates: the bad parts</title><summary>html/template might not be a good programming language.</summary><updated>2025-05-12T00:00:00Z</updated><id>https://www.bruh.ltd/blog/go-templates-the-bad-parts/</id><link rel="alternate" href="https://www.bruh.ltd/blog/go-templates-the-bad-parts/"/><content type="html"><![CDATA[
                    <p><a href="https://gohugo.io/">Hugo</a> is a fascinating piece of software. Unlike other static site
generators which either give you a template engine and bare minimum
functionality you need to get along (like, say, <a href="https://www.getzola.org/">Zola</a>) or straight up
let you execute arbitrary JavaScript code (like, say, <a href="https://www.11ty.dev/">11ty</a>), Hugo is
different — it gives you a template engine and an absurdly wide range
of features on top of it, basically extending it into a real dynamic
programming language with <a href="https://gohugo.io/functions/collections/">list processing</a>, <a href="https://gohugo.io/functions/strings/">string manipulation</a>,
and <a href="https://gohugo.io/functions/fmt/">text formatting</a>. This is why I love it — it gives you a lot of
freedom without the responsibility of not falling down the npm rabbit
hole.</p>
<p>A major reason why this is possible is Hugo's template engine of
choice — <a href="https://pkg.go.dev/text/template">Go templates</a>. They let you simply hook up a bunch of
structures and functions to it and make Go's runtime reflection magic
handle the rest. In no uncertain terms, they turn Go, a compiled
language with a rich package ecosystem, into a scripting language —
all you need to do is expose the things you want to the user. As a
basic concept, this is groundbreaking, and Hugo takes full advantage
of it, giving you nice stuff like <a href="https://gohugo.io/content-management/image-processing/#article">image processing capabilities</a>,
<a href="https://gohugo.io/functions/os/">filesystem traversal capabilities</a>, the ability to <a href="https://gohugo.io/methods/resource/exif/">read image Exif
metadata</a>.</p>
<p>Unfortunately, Go templates are also full of design flaws and missed
opportunities that hold it back from its true potential, which I
slowly discovered while using Hugo for my websites over the course of
the past few years. Here they are, roughly in the order of
egregiousness:</p>











<hgroup>
    <h2 id="bad-design">
        Bad design
    </h2>

    <a href="#bad-design" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Bad design'</span>
    </a>
</hgroup>














<hgroup>
    <h3 id="0-==-0-0-is-false">
        0 == 0.0 is false
    </h3>

    <a href="#0-%3d%3d-0-0-is-false" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled '0 == 0.0 is false'</span>
    </a>
</hgroup>



<pre tabindex="0"><code>{{/* Throws no error, prints false. */}}
{{ eq 0 0.0 }}
</code></pre><p>Now, I know how bad this looks at first glance — it truly feels like
Go's authors are trolling you. Especially if your first glance at this
issue is after hours of debugging why your if statement fails to catch
if a variable is equal to 0, like what happened to me. But hold on
with me for a moment, there's actually a technical reason for it. Sort
of.</p>
<p>Go is a strongly typed programming language, meaning that if you try
to perform an arithmetic operation on 2 different types or pass one
type where another one is expected, it'll scream at you instead of
coercing your value to the right type. When it comes to numbers, it's
even stronger than other strongly typed languages like Python, and it
won't coerce an integer to a float. Take the following code, for
instance:</p>
<pre tabindex="0"><code>a := 0
b := 0.0

fmt.Println(a == b)
</code></pre><p>If you tried to compile it, Go would notice that the variable <code>a</code> is
an integer and the variable <code>b</code> is a float, and rightfully tell you
that you can't do it:</p>
<pre tabindex="0"><code>invalid operation: a == b (mismatched types int and float64)
</code></pre><p>Go templates inherit this property of being strongly typed. Unlike Go,
however, which is <em>statically</em> typed, Go templates are dynamically
typed, meaning that the same variable can be reassigned to a value of
a different type, which makes sense for a tiny template language. As
such, instead of reporting an error, like a strong static language
would, or coercing the values, like a weak language would, it silently
returns a <code>false</code> because the types don't match.</p>
<p>Except it's not quite that simple. Go does, in fact, coerce the
values, but only if both operands are literals, not variable
identifiers:</p>
<pre tabindex="0"><code>// Prints true
fmt.Println(0 == 0.0)
</code></pre><p>Go templates, on the other hand, don't perform coercion even in this
case and always treat the operands like Go would treat variable
identifiers, leading to complete chaos where Go templates' behavior
doesn't match Go's behavior.</p>











<hgroup>
    <h3 id="variable-assignment-is-a-footgun">
        Variable assignment is a footgun
    </h3>

    <a href="#variable-assignment-is-a-footgun" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Variable assignment is a footgun'</span>
    </a>
</hgroup>



<p>This is another case where Go templates do what Go does but in an
inconvenient way. As far as variables go in Go (pun intended), it's
about as follows:</p>
<ul>
<li>Variables can be declared with <code>var identifier = value</code>. There's
also syntactic sugar for this — <code>identifier := value</code> — and since it
saves you 3 whole key presses, everyone is using it instead.</li>
<li>You can assign a new value to the variable with <code>identifier = value</code>.</li>
<li>Variables are block scoped, meaning that if you enter a block like
the body of an if statement, you can declare a variable with the
same identifier as another variable without affecting the latter in
any way because your variable will only ever stay within that block.</li>
</ul>
<p>On its own, <code>:=</code> used for variable declaration and <code>=</code> used for
variable assignment sounds like a bad idea — it'd be really easy to
mix up the two of them and end declaring a new scoped variable instead
of assigning to an existing one, and you wouldn't use the <code>var identifier = value</code> syntax out of the need to conform to the agreed
upon code style.</p>
<p>But fear not! Go has us covered here. If you do mess up, you'll most
likely create a variable that's declared and then never used, which Go
will scream at you about and not let you compile your project:</p>
<pre tabindex="0"><code>declared and not used: identifier
</code></pre><p>What do Go templates do in this case? Nothing:</p>
<pre tabindex="0"><code>{{ $meal := .PotatoChips }}

{{ if $isBeforeMidnight }}
    {{/* Throws no error. */}}
    {{ $meal := .BuyFood &#34;healthy&#34; }}
{{ end }}

{{/* Always .PotatoChips */}}
{{ $meal }}
</code></pre><p>And you can't even use the <code>var identifier = value</code> syntax here
because it doesn't exist in Go templates.</p>











<hgroup>
    <h3 id="there-s-nil-but-no-nil-literal">
        There's nil but no nil literal
    </h3>

    <a href="#there-s-nil-but-no-nil-literal" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'There's nil but no nil literal'</span>
    </a>
</hgroup>



<p>This one is self-explanatory: In Go templates, <code>nil</code> exists as a
keyword but doesn't exist as a literal. You can compare values to
<code>nil</code> but can't assign a variable to it without resorting to hacks:</p>
<pre tabindex="0"><code>{{ $dict := dict }}
{{ $nil := index $dict &#34;non-existent key&#34; }}

{{/* Prints &lt;nil&gt;. */}}
{{ print $nil }}

{{/* Prints &lt;nil&gt;. */}}
{{ if eq $nil nil }}
    {{ print $nil }}
{{ end }}

{{/* Throws an error. */}}
{{ $notNil := nil }}
</code></pre><p>To be completely fair, the practical impact of this is negligible —
it's at most a nuisance that you can't set a variable to an undefined
value in the few cases where you need it. But from a language design
standpoint, this is extremely cursed. An unrepresentable primitive is
not a thing you see often in other languages.</p>











<hgroup>
    <h3 id="there-s-no-ternary-operator">
        There's no ternary operator
    </h3>

    <a href="#there-s-no-ternary-operator" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'There's no ternary operator'</span>
    </a>
</hgroup>



<p>Let's say you want to have a variable that has 1 of 2 possible values,
picked depending on whether a certain condition is satisfied. In Hugo,
you can do it like this:</p>
<pre tabindex="0"><code>{{ $meal := cond $isBeforeMidnight
    (.BuyFood &#34;healthy&#34;)
    .Fridge.Contents.Extract
}}
</code></pre><p>There are 2 problems with this: First, you can only do it in Hugo.
<code>cond</code> is not a thing in Go templates by default. Second, there's a
bug in this code. Since Hugo couldn't add a new keyword to the
language, they had to make <code>cond</code> a function. And since functions
don't do short circuit evaluation like, say, an <code>and</code> keyword, <code>cond</code>
will evaluate both possible values regardless of the condition,
leading to hard to diagnose side effects.</p>
<p>There's only one way to work around this — use an if statement:</p>
<pre tabindex="0"><code>{{/* No nil, baby! */}}
{{ $meal := false }}

{{ if $isBeforeMidnight }}
    {{ $meal = .BuyFood &#34;healthy&#34; }}
{{ else }}
    {{ $meal = .Fridge.Contents.Extract }}
{{ end }}
</code></pre><p>The difference in the number of braces speaks for itself.</p>











<hgroup>
    <h2 id="missed-opportunities">
        Missed opportunities
    </h2>

    <a href="#missed-opportunities" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Missed opportunities'</span>
    </a>
</hgroup>














<hgroup>
    <h3 id="pipes-are-inflexible">
        Pipes are inflexible
    </h3>

    <a href="#pipes-are-inflexible" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Pipes are inflexible'</span>
    </a>
</hgroup>



<p>Go templates have a nifty feature that lets you chain function calls
without having to wrap everything in a million parentheses or making a
variable for every intermediate value:</p>
<pre tabindex="0"><code>{{ $meal := $potatoes | boil | mash | stickIn $stew }}
</code></pre><p>Is syntactic sugar for:</p>
<pre tabindex="0"><code>{{ $meal := stickIn $stew (mash (boil $potatoes)) }}
</code></pre><p>You may already see a problem with this: It always passes the value as
the last argument to the function. Let's say that it turns out the
function <code>stickIn</code> accepts the arguments in the opposite order. Now
you have to change the code above to:</p>
<pre tabindex="0"><code>{{ $meal := stickIn ($potatoes | mash | boil) $stew }}
</code></pre><p>And if you then want to call a method on the resulting value, it gets
even worse:</p>
<pre tabindex="0"><code>{{ $meal := (stickIn ($potatoes | mash | boil) $stew).Serve }}
</code></pre><p>Compare this to the <a href="https://github.com/tc39/proposal-pipeline-operator">ES proposal</a> for pipes in JavaScript that uses
placeholders for argument placement instead:</p>
<pre tabindex="0"><code>const meal = potatoes
    |&gt; mash(%)
    |&gt; boil(%)
    |&gt; stickIn(%, stew)
    |&gt; %.serve();
</code></pre><p>Much better. This is how pipes should be done, if you ask me.</p>











<hgroup>
    <h3 id="templates-can-t-return-a-value">
        Templates can't return a value
    </h3>

    <a href="#templates-can-t-return-a-value" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Templates can't return a value'</span>
    </a>
</hgroup>



<p>Go templates let you define and call inline templates in your code,
and I can't overstate how awesome this is. For example, if your
template host provides you with some rudimentary reflection
capabilities, which Hugo does, you can use it to print lists with
recursion:</p>
<pre tabindex="0"><code>{{ define &#34;print-slice&#34; }}
    [

    {{ range . }}
        {{ if reflect.IsSlice . }}
            {{ template &#34;print-slice&#34; . }}
        {{ else }}
            {{ . }}
        {{ end }}
    {{ end }}

    ]
{{ end }}

{{ template &#34;print-slice&#34; (slice 9 8 7 (slice 7 6 5) 4 32 true) }}
</code></pre><p>But unfortunately, printing is the only way you can output values in
vanilla Go templates. Hugo does have a workaround for this — inline
partials — but it's not without its flaws. Let's say you want to make
a function that calculates the factorial of a number:</p>
<pre tabindex="0"><code>{{ define &#34;partials/factorial&#34; }}
    {{ return (math.Product (seq 1 .)) }}
{{ end }}

{{ partial &#34;factorial&#34; 5 }}
</code></pre><p>This works correctly but only for positive values because <code>seq</code> will
start iterating backwards for negative values. If you try to fix it
the naive way:</p>
<pre tabindex="0"><code>{{ if gt . 1 }}
    {{ return (math.Product (seq 1 .)) }}
{{ else }}
    {{ return 1 }}
{{ end }}
</code></pre><p>You'll get an inscrutable error like this:</p>
<pre tabindex="0"><code>execute of template failed at &lt;return&gt;: wrong number of args for return: want 0 got 1
</code></pre><p>Because it doesn't work for the same reason <code>cond</code> can't short circuit
evaluate its arguments — <code>return</code> is just a function. Since it's not a
keyword, it can't preemptively stop the execution of a function. All
it can do is set a value somewhere and tell Hugo to later put it in
the right place. So instead, you have to do this:</p>
<pre tabindex="0"><code>{{ $result := 1 }}

{{ if gt . 0 }}
    {{ $result = math.Product (seq 1 .) }}
{{ end }}

{{ return $result }}
</code></pre><p>Go templates were <em>this close</em> to having user definable functions, but
they didn't add a return keyword. What a shame.</p>











<hgroup>
    <h2 id="conclusion">
        Conclusion
    </h2>

    <a href="#conclusion" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Conclusion'</span>
    </a>
</hgroup>



<p>If you're writing a new template engine, it'd be really cool if you
added the things Go templates do right without adding the things they
do wrong. Just sayin'.</p>

                ]]></content></entry><entry><title>Longest Web API type names</title><summary>A peculiar finding.</summary><updated>2025-05-02T00:00:00Z</updated><id>https://www.bruh.ltd/blog/longest-web-api-type-names/</id><link rel="alternate" href="https://www.bruh.ltd/blog/longest-web-api-type-names/"/><content type="html"><![CDATA[
                    <p>If you've browsed <a href="https://developer.mozilla.org/">MDN</a> recently, you may have noticed some Web API
types with really long names, including such bangers as
<a href="https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultReader"><code>ReadableStreamDefaultReader</code></a> and
<a href="https://developer.mozilla.org/en-US/docs/Web/API/FileSystemWritableFileStream"><code>FileSystemWritableFileStream</code></a>. If you've ever thought &quot;I
wonder what the longest one is&quot;, you're in luck — this is exactly what
this post is about.</p>











<hgroup>
    <h2 id="the-names">
        The names
    </h2>

    <a href="#the-names" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'The names'</span>
    </a>
</hgroup>














<hgroup>
    <h3 id="50&#43;-characters">
        50+ characters
    </h3>

    <a href="#50%2b-characters" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled '50+ characters'</span>
    </a>
</hgroup>



<ul>
<li><code>InterestGroupBiddingAndScoringScriptRunnerGlobalScope</code></li>
<li><code>WEBGL_multi_draw_instanced_base_vertex_base_instance</code></li>
</ul>











<hgroup>
    <h3 id="40&#43;-characters">
        40+ characters
    </h3>

    <a href="#40%2b-characters" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled '40+ characters'</span>
    </a>
</hgroup>



<ul>
<li><code>WEBGL_draw_instanced_base_vertex_base_instance</code></li>
<li><code>RunFunctionForSharedStorageSelectURLOperation</code></li>
<li><code>InterestGroupReportingScriptRunnerGlobalScope</code></li>
<li><code>WindowControlsOverlayGeometryChangeEventInit</code></li>
<li><code>InterestGroupBiddingScriptRunnerGlobalScope</code></li>
<li><code>InterestGroupScoringScriptRunnerGlobalScope</code></li>
<li><code>ContentVisibilityAutoStateChangeEventInit</code></li>
<li><code>TopLevelStorageAccessPermissionDescriptor</code></li>
<li><code>ProtectedAudiencePrivateAggregationConfig</code></li>
<li><code>AuthenticationExtensionsClientOutputsJSON</code></li>
<li><code>PresentationConnectionAvailableEventInit</code></li>
<li><code>PrivateNetworkAccessPermissionDescriptor</code></li>
<li><code>AuthenticationExtensionsClientInputsJSON</code></li>
<li><code>AuthenticationExtensionsLargeBlobOutputs</code></li>
<li><code>WindowControlsOverlayGeometryChangeEvent</code></li>
</ul>











<hgroup>
    <h3 id="30&#43;-characters">
        30+ characters
    </h3>

    <a href="#30%2b-characters" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled '30+ characters'</span>
    </a>
</hgroup>



<ul>
<li><code>SecurityPolicyViolationEventDisposition</code></li>
<li><code>IdentityCredentialRequestOptionsContext</code></li>
<li><code>MediaCapabilitiesKeySystemConfiguration</code></li>
<li><code>SanitizerElementNamespaceWithAttributes</code></li>
<li><code>AuthenticationExtensionsLargeBlobInputs</code></li>
<li><code>MLQuantizeDequantizeLinearSupportLimits</code></li>
<li><code>WEBGL_blend_equation_advanced_coherent</code></li>
<li><code>OrientationSensorLocalCoordinateSystem</code></li>
<li><code>SharedStorageRunOperationMethodOptions</code></li>
<li><code>PublicKeyCredentialCreationOptionsJSON</code></li>
<li><code>XRSessionSupportedPermissionDescriptor</code></li>
<li><code>ContentVisibilityAutoStateChangeEvent</code></li>
<li><code>AuthenticationExtensionsClientOutputs</code></li>
<li><code>NavigationCurrentEntryChangeEventInit</code></li>
<li><code>PrivateAttributionAggregationServices</code></li>
<li><code>SecurePaymentConfirmationAvailability</code></li>
<li><code>AuthenticationExtensionsPaymentInputs</code></li>
<li><code>SharedStoragePrivateAggregationConfig</code></li>
<li><code>HTMLSharedStorageWritableElementUtils</code></li>
<li><code>PublicKeyCredentialClientCapabilities</code></li>
<li><code>PublicKeyCredentialRequestOptionsJSON</code></li>
<li><code>IdentityCredentialRequestOptionsMode</code></li>
<li><code>AuthenticationExtensionsClientInputs</code></li>
<li><code>FileSystemHandlePermissionDescriptor</code></li>
<li><code>SVGFilterPrimitiveStandardAttributes</code></li>
<li><code>MockCapturePromptResultConfiguration</code></li>
<li><code>PermissionsPolicyViolationReportBody</code></li>
<li><code>PrivateAttributionAggregationService</code></li>
<li><code>PresentationConnectionAvailableEvent</code></li>
<li><code>PresentationConnectionCloseEventInit</code></li>
<li><code>CollectedClientAdditionalPaymentData</code></li>
<li><code>InterestGroupScriptRunnerGlobalScope</code></li>
<li><code>AuthenticatorAttestationResponseJSON</code></li>
<li><code>MLConvTranspose2dFilterOperandLayout</code></li>
<li><code>IdentityCredentialDisconnectOptions</code></li>
<li><code>SVGComponentTransferFunctionElement</code></li>
<li><code>ImageBitmapRenderingContextSettings</code></li>
<li><code>NavigationUpdateCurrentEntryOptions</code></li>
<li><code>PerformanceLongAnimationFrameTiming</code></li>
<li><code>PrivateAttributionImpressionOptions</code></li>
<li><code>PrivateAttributionConversionOptions</code></li>
<li><code>ReadableStreamBYOBReaderReadOptions</code></li>
<li><code>BluetoothLEScanPermissionDescriptor</code></li>
<li><code>BluetoothManufacturerDataFilterInit</code></li>
<li><code>GPURenderPassDepthStencilAttachment</code></li>
<li><code>WEBGL_compressed_texture_s3tc_srgb</code></li>
<li><code>AccelerometerLocalCoordinateSystem</code></li>
<li><code>AttributionReportingRequestOptions</code></li>
<li><code>PerformanceObserverCallbackOptions</code></li>
<li><code>PrivateAttributionConversionResult</code></li>
<li><code>RemotePlaybackAvailabilityCallback</code></li>
<li><code>SharedStorageModifierMethodOptions</code></li>
<li><code>MediaStreamTrackAudioSourceOptions</code></li>
<li><code>AuthenticatorAssertionResponseJSON</code></li>
<li><code>PublicKeyCredentialCreationOptions</code></li>
<li><code>AuthenticationExtensionsPRFOutputs</code></li>
<li><code>RTCPeerConnectionIceErrorEventInit</code></li>
<li><code>XRTransientInputHitTestOptionsInit</code></li>
<li><code>FederatedCredentialRequestOptions</code></li>
<li><code>DocumentPictureInPictureEventInit</code></li>
<li><code>OffscreenCanvasRenderingContext2D</code></li>
<li><code>NavigationCurrentEntryChangeEvent</code></li>
<li><code>OnBeforeUnloadEventHandlerNonNull</code></li>
<li><code>MagnetometerLocalCoordinateSystem</code></li>
<li><code>DeviceMotionEventAccelerationInit</code></li>
<li><code>DeviceMotionEventRotationRateInit</code></li>
<li><code>PresentationConnectionCloseReason</code></li>
<li><code>AuctionReportBuyerDebugModeConfig</code></li>
<li><code>BluetoothRemoteGATTCharacteristic</code></li>
<li><code>BluetoothCharacteristicProperties</code></li>
<li><code>PublicKeyCredentialUserEntityJSON</code></li>
<li><code>PublicKeyCredentialDescriptorJSON</code></li>
<li><code>PublicKeyCredentialRequestOptions</code></li>
<li><code>AuthenticationExtensionsPRFValues</code></li>
<li><code>AuthenticationExtensionsPRFInputs</code></li>
<li><code>MLBatchNormalizationSupportLimits</code></li>
<li><code>SecurityPolicyViolationEventInit</code></li>
<li><code>IdentityCredentialRequestOptions</code></li>
<li><code>HandwritingRecognizerQueryResult</code></li>
<li><code>CanvasRenderingContext2DSettings</code></li>
<li><code>CameraDevicePermissionDescriptor</code></li>
<li><code>PresentationConnectionCloseEvent</code></li>
<li><code>SecurePaymentConfirmationRequest</code></li>
<li><code>TransformStreamDefaultController</code></li>
<li><code>DirectFromSellerSignalsForSeller</code></li>
<li><code>AudioWorkletProcessorConstructor</code></li>
<li><code>AuthenticatorAttestationResponse</code></li>
<li><code>VideoEncoderEncodeOptionsForHevc</code></li>
<li><code>GPURenderBundleEncoderDescriptor</code></li>
<li><code>WebTransportDatagramDuplexStream</code></li>
<li><code>EXT_disjoint_timer_query_webgl2</code></li>
<li><code>ExtendableCookieChangeEventInit</code></li>
<li><code>PaintRenderingContext2DSettings</code></li>
<li><code>DigitalCredentialRequestOptions</code></li>
<li><code>DocumentPictureInPictureOptions</code></li>
<li><code>FileSystemCreateWritableOptions</code></li>
<li><code>ObservableInspectorAbortHandler</code></li>
<li><code>PushSubscriptionChangeEventInit</code></li>
<li><code>SharedStorageWorkletGlobalScope</code></li>
<li><code>SpeechRecognitionErrorEventInit</code></li>
<li><code>ReadableStreamDefaultController</code></li>
<li><code>WritableStreamDefaultController</code></li>
<li><code>PAExtendedHistogramContribution</code></li>
<li><code>DirectFromSellerSignalsForBuyer</code></li>
<li><code>BluetoothManufacturerDataFilter</code></li>
<li><code>BluetoothLEScanPermissionResult</code></li>
<li><code>OfflineAudioCompletionEventInit</code></li>
<li><code>MediaStreamAudioDestinationNode</code></li>
<li><code>MediaStreamTrackAudioSourceNode</code></li>
<li><code>AttestationConveyancePreference</code></li>
<li><code>VideoEncoderEncodeOptionsForAv1</code></li>
<li><code>VideoEncoderEncodeOptionsForAvc</code></li>
<li><code>VideoEncoderEncodeOptionsForVp9</code></li>
<li><code>EncodedAudioChunkOutputCallback</code></li>
<li><code>EncodedVideoChunkOutputCallback</code></li>
<li><code>WebGL2RenderingContextOverloads</code></li>
<li><code>GPUExternalTextureBindingLayout</code></li>
<li><code>RTCRemoteOutboundRtpStreamStats</code></li>
<li><code>RTCRtpHeaderExtensionParameters</code></li>
<li><code>RTCRtpHeaderExtensionCapability</code></li>
<li><code>WebTransportBidirectionalStream</code></li>
<li><code>USBIsochronousOutTransferPacket</code></li>
<li><code>USBIsochronousOutTransferResult</code></li>
<li><code>EXT_texture_filter_anisotropic</code></li>
<li><code>SVGAnimatedPreserveAspectRatio</code></li>
<li><code>WEBGL_compressed_texture_pvrtc</code></li>
<li><code>HTMLAttributionSrcElementUtils</code></li>
<li><code>CredentialMediationRequirement</code></li>
<li><code>SpatialNavigationSearchOptions</code></li>
<li><code>CharacterBoundsUpdateEventInit</code></li>
<li><code>BrowserCaptureMediaStreamTrack</code></li>
<li><code>IdentityProviderRequestOptions</code></li>
<li><code>IdentityProviderClientMetadata</code></li>
<li><code>FileSystemPermissionDescriptor</code></li>
<li><code>GyroscopeLocalCoordinateSystem</code></li>
<li><code>MediaTrackSupportedConstraints</code></li>
<li><code>MockCaptureDeviceConfiguration</code></li>
<li><code>NotificationPermissionCallback</code></li>
<li><code>ObservableSubscriptionCallback</code></li>
<li><code>ObservableEventListenerOptions</code></li>
<li><code>SanitizerElementWithAttributes</code></li>
<li><code>SurfaceSwitchingPreferenceEnum</code></li>
<li><code>ReadableStreamGetReaderOptions</code></li>
<li><code>UnderlyingSourceCancelCallback</code></li>
<li><code>AuctionRealTimeReportingConfig</code></li>
<li><code>BluetoothServiceDataFilterInit</code></li>
<li><code>AudioContextRenderSizeCategory</code></li>
<li><code>MediaElementAudioSourceOptions</code></li>
<li><code>AuthenticatorAssertionResponse</code></li>
<li><code>AuthenticatorSelectionCriteria</code></li>
<li><code>NavigatorAutomationInformation</code></li>
<li><code>WebGLRenderingContextOverloads</code></li>
<li><code>GPUStorageTextureBindingLayout</code></li>
<li><code>GPUShaderModuleCompilationHint</code></li>
<li><code>GPUCopyExternalImageSourceInfo</code></li>
<li><code>MLInstanceNormalizationOptions</code></li>
<li><code>RTCIdentityProviderGlobalScope</code></li>
<li><code>RTCRemoteInboundRtpStreamStats</code></li>
<li><code>RTCPeerConnectionErrorCallback</code></li>
<li><code>RTCLocalSessionDescriptionInit</code></li>
<li><code>RTCPeerConnectionIceErrorEvent</code></li>
<li><code>WebTransportReceiveStreamStats</code></li>
<li><code>USBIsochronousInTransferPacket</code></li>
<li><code>USBIsochronousInTransferResult</code></li>
</ul>











<hgroup>
    <h3 id="25&#43;-characters">
        25+ characters
    </h3>

    <a href="#25%2b-characters" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled '25+ characters'</span>
    </a>
</hgroup>



<ul>
<li><code>OES_texture_half_float_linear</code></li>
<li><code>WEBGL_compressed_texture_astc</code></li>
<li><code>WEBGL_compressed_texture_etc1</code></li>
<li><code>WEBGL_compressed_texture_s3tc</code></li>
<li><code>ClipboardPermissionDescriptor</code></li>
<li><code>CaretPositionFromPointOptions</code></li>
<li><code>DocumentPictureInPictureEvent</code></li>
<li><code>MediaKeySystemMediaCapability</code></li>
<li><code>SVGFEComponentTransferElement</code></li>
<li><code>FileSystemGetDirectoryOptions</code></li>
<li><code>IntersectionObserverEntryInit</code></li>
<li><code>MediaCapabilitiesDecodingInfo</code></li>
<li><code>MediaCapabilitiesEncodingInfo</code></li>
<li><code>CanvasCaptureMediaStreamTrack</code></li>
<li><code>MediaStreamTrackProcessorInit</code></li>
<li><code>DeviceMotionEventAcceleration</code></li>
<li><code>DeviceMotionEventRotationRate</code></li>
<li><code>PaymentRequestUpdateEventInit</code></li>
<li><code>SharedStorageSetMethodOptions</code></li>
<li><code>SharedStorageWorkletNavigator</code></li>
<li><code>SpeechSynthesisErrorEventInit</code></li>
<li><code>ReadableStreamIteratorOptions</code></li>
<li><code>UnderlyingSourceStartCallback</code></li>
<li><code>WebAssemblyInstantiatedSource</code></li>
<li><code>BluetoothPermissionDescriptor</code></li>
<li><code>BluetoothAdvertisingEventInit</code></li>
<li><code>BluetoothRemoteGATTDescriptor</code></li>
<li><code>MediaStreamAudioSourceOptions</code></li>
<li><code>AllAcceptedCredentialsOptions</code></li>
<li><code>PublicKeyCredentialParameters</code></li>
<li><code>PublicKeyCredentialUserEntity</code></li>
<li><code>PublicKeyCredentialDescriptor</code></li>
<li><code>GPUComputePassTimestampWrites</code></li>
<li><code>SFrameTransformErrorEventType</code></li>
<li><code>SFrameTransformErrorEventInit</code></li>
<li><code>RTCStatsIceCandidatePairState</code></li>
<li><code>RTCSessionDescriptionCallback</code></li>
<li><code>RTCIceServerTransportProtocol</code></li>
<li><code>RTCPeerConnectionIceEventInit</code></li>
<li><code>WebTransportDatagramsWritable</code></li>
<li><code>WebTransportCongestionControl</code></li>
<li><code>WebTransportSendStreamOptions</code></li>
<li><code>XRTransientInputHitTestSource</code></li>
<li><code>XRTransientInputHitTestResult</code></li>
<li><code>XRInputSourcesChangeEventInit</code></li>
<li><code>SecurityPolicyViolationEvent</code></li>
<li><code>EXT_texture_compression_bptc</code></li>
<li><code>EXT_texture_compression_rgtc</code></li>
<li><code>WEBGL_compressed_texture_etc</code></li>
<li><code>BackgroundFetchFailureReason</code></li>
<li><code>BackgroundFetchUpdateUIEvent</code></li>
<li><code>ScriptingPolicyViolationType</code></li>
<li><code>ViewTransitionUpdateCallback</code></li>
<li><code>SVGFESpecularLightingElement</code></li>
<li><code>FileSystemWritableFileStream</code></li>
<li><code>IntersectionObserverCallback</code></li>
<li><code>ConstrainDOMStringParameters</code></li>
<li><code>PaymentMethodChangeEventInit</code></li>
<li><code>PerformanceObserverEntryList</code></li>
<li><code>GenerateTestReportParameters</code></li>
<li><code>SharedStorageUrlWithMetadata</code></li>
<li><code>SpeechRecognitionAlternative</code></li>
<li><code>UnderlyingSourcePullCallback</code></li>
<li><code>ReadableByteStreamController</code></li>
<li><code>TransformerTransformCallback</code></li>
<li><code>BluetoothManufacturerDataMap</code></li>
<li><code>BluetoothDeviceEventHandlers</code></li>
<li><code>VideoTransferCharacteristics</code></li>
<li><code>GPUExternalTextureDescriptor</code></li>
<li><code>GPUBindGroupLayoutDescriptor</code></li>
<li><code>GPUComputePipelineDescriptor</code></li>
<li><code>GPUCopyExternalImageDestInfo</code></li>
<li><code>GPURenderPassTimestampWrites</code></li>
<li><code>GPURenderPassColorAttachment</code></li>
<li><code>MLRecurrentNetworkActivation</code></li>
<li><code>MLNormalizationSupportLimits</code></li>
<li><code>RTCEncodedVideoFrameMetadata</code></li>
<li><code>RTCEncodedAudioFrameMetadata</code></li>
<li><code>RTCIdentityProviderRegistrar</code></li>
<li><code>USBControlTransferParameters</code></li>
<li><code>EXT_color_buffer_half_float</code></li>
<li><code>KHR_parallel_shader_compile</code></li>
<li><code>BackgroundFetchRegistration</code></li>
<li><code>ClipboardUnsanitizedFormats</code></li>
<li><code>ExtendableCookieChangeEvent</code></li>
<li><code>AnimationWorkletGlobalScope</code></li>
<li><code>AnimatorInstanceConstructor</code></li>
<li><code>IntrinsicSizesResultOptions</code></li>
<li><code>TextEncoderEncodeIntoResult</code></li>
<li><code>MediaKeySystemConfiguration</code></li>
<li><code>MediaKeySessionClosedReason</code></li>
<li><code>IdentityProviderAccountList</code></li>
<li><code>SVGFEDiffuseLightingElement</code></li>
<li><code>SVGFEDisplacementMapElement</code></li>
<li><code>HandwritingHintsQueryResult</code></li>
<li><code>ImageBitmapRenderingContext</code></li>
<li><code>OffscreenRenderingContextId</code></li>
<li><code>NavigatorConcurrentHardware</code></li>
<li><code>InputDeviceCapabilitiesInit</code></li>
<li><code>KeySystemTrackConfiguration</code></li>
<li><code>MockMicrophoneConfiguration</code></li>
<li><code>PerformanceNavigationTiming</code></li>
<li><code>NavigatorNetworkInformation</code></li>
<li><code>PaymentRequestDetailsUpdate</code></li>
<li><code>PerformanceObserverCallback</code></li>
<li><code>PresentationConnectionState</code></li>
<li><code>PushSubscriptionOptionsInit</code></li>
<li><code>PushSubscriptionChangeEvent</code></li>
<li><code>SanitizerAttributeNamespace</code></li>
<li><code>TaskPriorityChangeEventInit</code></li>
<li><code>PaymentCredentialInstrument</code></li>
<li><code>ServiceWorkerUpdateViaCache</code></li>
<li><code>SharedStorageModifierMethod</code></li>
<li><code>SharedStorageWorkletOptions</code></li>
<li><code>SpeechRecognitionErrorEvent</code></li>
<li><code>SpeechRecognitionResultList</code></li>
<li><code>SpeechRecognitionPhraseList</code></li>
<li><code>ReadableStreamGenericReader</code></li>
<li><code>ReadableStreamDefaultReader</code></li>
<li><code>UnderlyingSinkStartCallback</code></li>
<li><code>UnderlyingSinkWriteCallback</code></li>
<li><code>UnderlyingSinkCloseCallback</code></li>
<li><code>UnderlyingSinkAbortCallback</code></li>
<li><code>WritableStreamDefaultWriter</code></li>
<li><code>IterationCompositeOperation</code></li>
<li><code>BasePropertyIndexedKeyframe</code></li>
<li><code>CharacteristicEventHandlers</code></li>
<li><code>BluetoothCharacteristicUUID</code></li>
<li><code>OTPCredentialRequestOptions</code></li>
<li><code>AudioContextLatencyCategory</code></li>
<li><code>OfflineAudioCompletionEvent</code></li>
<li><code>MediaElementAudioSourceNode</code></li>
<li><code>AudioWorkletProcessCallback</code></li>
<li><code>PublicKeyCredentialRpEntity</code></li>
<li><code>UserVerificationRequirement</code></li>
<li><code>GPUPipelineLayoutDescriptor</code></li>
<li><code>GPURenderPipelineDescriptor</code></li>
<li><code>GPUCommandEncoderDescriptor</code></li>
<li><code>GPUUncapturedErrorEventInit</code></li>
<li><code>MLBatchNormalizationOptions</code></li>
<li><code>MLConv2dFilterOperandLayout</code></li>
<li><code>MLRecurrentNetworkDirection</code></li>
<li><code>MLLayerNormalizationOptions</code></li>
<li><code>RTCEncodedVideoFrameOptions</code></li>
<li><code>RTCEncodedAudioFrameOptions</code></li>
<li><code>RTCIdentityValidationResult</code></li>
<li><code>RTCRtpSynchronizationSource</code></li>
<li><code>WebTransportReliabilityMode</code></li>
<li><code>WebTransportConnectionStats</code></li>
<li><code>WebTransportSendStreamStats</code></li>
<li><code>SummarizerCreateCoreOptions</code></li>
<li><code>AccelerometerSensorOptions</code></li>
<li><code>HighlightsFromPointOptions</code></li>
<li><code>SpatialNavigationDirection</code></li>
<li><code>StartViewTransitionOptions</code></li>
<li><code>CharacterBoundsUpdateEvent</code></li>
<li><code>SVGFEConvolveMatrixElement</code></li>
<li><code>FileSystemReadWriteOptions</code></li>
<li><code>FileSystemSyncAccessHandle</code></li>
<li><code>HandwritingModelConstraint</code></li>
<li><code>HandwritingRecognitionType</code></li>
<li><code>HTMLFormControlsCollection</code></li>
<li><code>NavigationInterceptOptions</code></li>
<li><code>NavigationInterceptHandler</code></li>
<li><code>OnErrorEventHandlerNonNull</code></li>
<li><code>OnBeforeUnloadEventHandler</code></li>
<li><code>StructuredSerializeOptions</code></li>
<li><code>DedicatedWorkerGlobalScope</code></li>
<li><code>ConstrainPoint2DParameters</code></li>
<li><code>DelegatedInkTrailPresenter</code></li>
<li><code>MediaDecodingConfiguration</code></li>
<li><code>MediaEncodingConfiguration</code></li>
<li><code>ConstrainBooleanParameters</code></li>
<li><code>DeviceOrientationEventInit</code></li>
<li><code>MemoryAttributionContainer</code></li>
<li><code>PrivateAttributionProtocol</code></li>
<li><code>PresentationConnectionList</code></li>
<li><code>NetworkInformationSaveData</code></li>
<li><code>CollectedClientPaymentData</code></li>
<li><code>ExtendableMessageEventInit</code></li>
<li><code>SpeechRecognitionErrorCode</code></li>
<li><code>SpeechRecognitionEventInit</code></li>
<li><code>SVGAnimateTransformElement</code></li>
<li><code>AuctionAdInterestGroupSize</code></li>
<li><code>ProtectedAudienceUtilities</code></li>
<li><code>ReportResultBrowserSignals</code></li>
<li><code>VideoFrameCallbackMetadata</code></li>
<li><code>AnimationPlaybackEventInit</code></li>
<li><code>BluetoothServiceDataFilter</code></li>
<li><code>BluetoothPermissionStorage</code></li>
<li><code>WatchAdvertisementsOptions</code></li>
<li><code>BluetoothRemoteGATTService</code></li>
<li><code>OTPCredentialTransportType</code></li>
<li><code>OfflineAudioContextOptions</code></li>
<li><code>MediaStreamAudioSourceNode</code></li>
<li><code>AuthenticationResponseJSON</code></li>
<li><code>CredentialPropertiesOutput</code></li>
<li><code>WebGLShaderPrecisionFormat</code></li>
<li><code>WebGL2RenderingContextBase</code></li>
<li><code>GPUCopyExternalImageSource</code></li>
<li><code>GPUCommandBufferDescriptor</code></li>
<li><code>MLSingleInputSupportLimits</code></li>
<li><code>RTCIdentityAssertionResult</code></li>
<li><code>RTCIdentityProviderDetails</code></li>
<li><code>RTCIdentityProviderOptions</code></li>
<li><code>RTCQualityLimitationReason</code></li>
<li><code>RTCRtpTransceiverDirection</code></li>
<li><code>RTCDTMFToneChangeEventInit</code></li>
<li><code>SummarizerSummarizeOptions</code></li>
<li><code>XMLHttpRequestResponseType</code></li>
<li><code>IDBVersionChangeEventInit</code></li>
<li><code>WindowOrWorkerGlobalScope</code></li>
<li><code>WebGLVertexArrayObjectOES</code></li>
<li><code>SVGTextPositioningElement</code></li>
<li><code>WEBGL_debug_renderer_info</code></li>
<li><code>ServiceWorkerRegistration</code></li>
<li><code>CredentialCreationOptions</code></li>
<li><code>ScriptingPolicyReportBody</code></li>
<li><code>CSSPositionTryDescriptors</code></li>
<li><code>CSSVariableReferenceValue</code></li>
<li><code>CSSMatrixComponentOptions</code></li>
<li><code>TextFormatUpdateEventInit</code></li>
<li><code>FileSystemDirectoryReader</code></li>
<li><code>FileSystemEntriesCallback</code></li>
<li><code>IdentityProviderWellKnown</code></li>
<li><code>IdentityProviderAPIConfig</code></li>
<li><code>IdentityAssertionResponse</code></li>
<li><code>FenceReportingDestination</code></li>
<li><code>FileSystemDirectoryHandle</code></li>
<li><code>HandwritingDrawingSegment</code></li>
<li><code>HTMLHyperlinkElementUtils</code></li>
<li><code>OffscreenRenderingContext</code></li>
<li><code>NavigationNavigateOptions</code></li>
<li><code>NavigationHistoryBehavior</code></li>
<li><code>PromiseRejectionEventInit</code></li>
<li><code>IntersectionObserverEntry</code></li>
<li><code>PerformanceLongTaskTiming</code></li>
<li><code>MagnetometerSensorOptions</code></li>
<li><code>MediaStreamTrackEventInit</code></li>
<li><code>MediaStreamTrackProcessor</code></li>
<li><code>MediaSessionPlaybackState</code></li>
<li><code>MediaSessionActionHandler</code></li>
<li><code>MediaSessionActionDetails</code></li>
<li><code>AbsoluteOrientationSensor</code></li>
<li><code>RelativeOrientationSensor</code></li>
<li><code>PaymentRequestUpdateEvent</code></li>
<li><code>PictureInPictureEventInit</code></li>
<li><code>ReportingObserverCallback</code></li>
<li><code>PerformanceResourceTiming</code></li>
<li><code>SanitizerElementNamespace</code></li>
<li><code>SchedulerPostTaskCallback</code></li>
<li><code>CaptureStartFocusBehavior</code></li>
<li><code>SelfCapturePreferenceEnum</code></li>
<li><code>SystemAudioPreferenceEnum</code></li>
<li><code>DisplayMediaStreamOptions</code></li>
<li><code>DisplayCaptureSurfaceType</code></li>
<li><code>SharedStorageAppendMethod</code></li>
<li><code>SharedStorageDeleteMethod</code></li>
<li><code>SpeechSynthesisErrorEvent</code></li>
<li><code>ReadableStreamBYOBRequest</code></li>
<li><code>TransformerCancelCallback</code></li>
<li><code>ByteLengthQueuingStrategy</code></li>
<li><code>AuctionAdInterestGroupKey</code></li>
<li><code>AuctionReportBuyersConfig</code></li>
<li><code>URLPatternComponentResult</code></li>
<li><code>PerformanceMeasureOptions</code></li>
<li><code>VideoFrameRequestCallback</code></li>
<li><code>BluetoothLEScanFilterInit</code></li>
<li><code>BluetoothPermissionResult</code></li>
<li><code>BluetoothAdvertisingEvent</code></li>
<li><code>BluetoothRemoteGATTServer</code></li>
<li><code>DynamicsCompressorOptions</code></li>
<li><code>CurrentUserDetailsOptions</code></li>
<li><code>PublicKeyCredentialEntity</code></li>
<li><code>VideoEncoderEncodeOptions</code></li>
<li><code>EncodedAudioChunkMetadata</code></li>
<li><code>EncodedVideoChunkMetadata</code></li>
<li><code>WebGLRenderingContextBase</code></li>
<li><code>GPUShaderModuleDescriptor</code></li>
<li><code>GPUCompilationMessageType</code></li>
<li><code>GPUPipelineDescriptorBase</code></li>
<li><code>GPURenderBundleDescriptor</code></li>
<li><code>MLLogicalNotSupportLimits</code></li>
<li><code>SFrameTransformErrorEvent</code></li>
<li><code>GenerateAssertionCallback</code></li>
<li><code>ValidateAssertionCallback</code></li>
<li><code>RTCReceivedRtpStreamStats</code></li>
<li><code>RTCOutboundRtpStreamStats</code></li>
<li><code>RTCSessionDescriptionInit</code></li>
<li><code>RTCPeerConnectionIceEvent</code></li>
<li><code>WebTransportDatagramStats</code></li>
<li><code>WebTransportReceiveStream</code></li>
<li><code>XRInputSourcesChangeEvent</code></li>
<li><code>XRReferenceSpaceEventInit</code></li>
<li><code>RewriterCreateCoreOptions</code></li>
<li><code>XMLHttpRequestEventTarget</code>
</li>
</ul>











<hgroup>
    <h2 id="how-to-reproduce-this-list">
        How to reproduce this list
    </h2>

    <a href="#how-to-reproduce-this-list" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'How to reproduce this list'</span>
    </a>
</hgroup>



<p>Use the following Node script. It uses the <a href="https://github.com/w3c/webref/tree/main/packages/idl">WebIDL definitions</a> from
every Web standard to do its job. And yes, I am as surprised as you
that they not only have a JavaScript API for this, but it's also all
in one place and easy to use.</p>
<pre tabindex="0"><code>import idl from &#34;@webref/idl&#34;;

const specs = await idl.parseAll();
const asts = Object.values(specs);
const definitions = asts.flat();

const allNames = definitions
    .map(definition =&gt; definition.name)
    .filter(name =&gt; name != undefined);

const uniqueNames = Array.from(new Set(allNames))
    .toSorted((a, b) =&gt; b.length - a.length);

const THRESHOLD = 25;
const longNames = uniqueNames.filter(name =&gt; name.length &gt;= THRESHOLD);

const byCharacters = name =&gt; Math.floor(name.length / 10) * 10;
const namesByCharacters =
    Object.entries(Object.groupBy(longNames, byCharacters))
    .map(entry =&gt; ({characters: entry[0], names: entry[1]}))
    .toSorted((a, b) =&gt; b.characters - a.characters);

for (const group of namesByCharacters) {
    const characters = group == namesByCharacters.at(-1)
        ? THRESHOLD
        : group.characters;

    console.log(`### ${characters}+ characters\n`);

    for (const name of group.names) {
        console.log(`* \`${name}\``);
    }

    console.log();
}
</code></pre>
                ]]></content></entry><entry><title>Programming language file extensions that match an ISO 3166-1 alpha-2 country code</title><summary>Why does this article even exist?</summary><updated>2025-02-08T00:00:00Z</updated><id>https://www.bruh.ltd/blog/programming-language-file-extensions-that-match-an-iso-3166-1-alpha-2-country-code/</id><link rel="alternate" href="https://www.bruh.ltd/blog/programming-language-file-extensions-that-match-an-iso-3166-1-alpha-2-country-code/"/><content type="html"><![CDATA[
                    <p>So there's this standard called <a href="https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2">ISO 3166-1 alpha-2</a> that defines a 2
letter code for every country on the planet (like ME = Montenegro) and
a bunch of places that aren't countries (like EU = European Union).
You've probably encountered such a code before in top level domain
names (<a href="https://en.wikipedia.org/wiki/.im">.im</a> belongs to the Isle of Man) and on Discord (typing
<code>:flag_fm:</code> yields a <a href="https://en.wikipedia.org/wiki/Flag_of_the_Federated_States_of_Micronesia">🇫🇲</a> emoji).</p>
<p>One of these codes is RS (= Serbia). Either by a sheer coincidence or
someone playing 5D chess, .rs is also the file extension for the Rust
programming language, which is why the domain name of every other Rust
project now belongs to Serbia. This made me curious about other cases
like this, so here's an incomplete list of programming languages,
domain-specific languages, markup languages, etc which file extensions
match a country code. If you think something is missing, let me know!</p>

    

    <div class="table-wrapper">
        <table>
            <thead>
                <tr>
                    <th>Code</th>
                    <th>Flag</th>
                    <th>Language</th>
                    <th>Country</th>
                </tr>
            </thead>


            <tbody>
                
                    
                    
                    

                    <tr>
                        <td>AM</td>
                        <td>
        

        
        
        

        

        🇦🇲
    </td>
                        <td>Automake</td>
                        <td>Armenia</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>AS</td>
                        <td>
        

        
        
        

        

        🇦🇸
    </td>
                        <td>ActionScript</td>
                        <td>American Samoa</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>CC</td>
                        <td>
        

        
        
        

        

        🇨🇨
    </td>
                        <td>C++</td>
                        <td>Cocos Islands</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>EC</td>
                        <td>
        

        
        
        

        

        🇪🇨
    </td>
                        <td>eC</td>
                        <td>Ecuador</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>ES</td>
                        <td>
        

        
        
        

        

        🇪🇸
    </td>
                        <td>ECMAScript</td>
                        <td>Spain</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>GY</td>
                        <td>
        

        
        
        

        

        🇬🇾
    </td>
                        <td>Groovy</td>
                        <td>Guyana</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>IN</td>
                        <td>
        

        
        
        

        

        🇮🇳
    </td>
                        <td>Autoconf</td>
                        <td>India</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>MD</td>
                        <td>
        

        
        
        

        

        🇲🇩
    </td>
                        <td>Markdown</td>
                        <td>Moldova</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>MK</td>
                        <td>
        

        
        
        

        

        🇲🇰
    </td>
                        <td>Makefile</td>
                        <td>North Macedonia</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>MM</td>
                        <td>
        

        
        
        

        

        🇲🇲
    </td>
                        <td>Objective C</td>
                        <td>Myanmar</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>PL</td>
                        <td>
        

        
        
        

        

        🇵🇱
    </td>
                        <td>Perl, PL/I, Prolog</td>
                        <td>Poland</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>PS</td>
                        <td>
        

        
        
        

        

        🇵🇸
    </td>
                        <td>PostScript</td>
                        <td>Palestine</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>PY</td>
                        <td>
        

        
        
        

        

        🇵🇾
    </td>
                        <td>Python</td>
                        <td>Paraguay</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>RS</td>
                        <td>
        

        
        
        

        

        🇷🇸
    </td>
                        <td>Rust</td>
                        <td>Serbia</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>RU</td>
                        <td>
        

        
        
        

        

        🇷🇺
    </td>
                        <td>Ruby</td>
                        <td>Russia</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>SB</td>
                        <td>
        

        
        
        

        

        🇸🇧
    </td>
                        <td>Scratch</td>
                        <td>Solomon Islands</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>SC</td>
                        <td>
        

        
        
        

        

        🇸🇨
    </td>
                        <td>Scala</td>
                        <td>Seychelles</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>SH</td>
                        <td>
        

        
        
        

        

        🇸🇭
    </td>
                        <td>Unix Shell</td>
                        <td>Saint Helena</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>SL</td>
                        <td>
        

        
        
        

        

        🇸🇱
    </td>
                        <td>S-Lang</td>
                        <td>Sierra Leone</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>SM</td>
                        <td>
        

        
        
        

        

        🇸🇲
    </td>
                        <td>SmallTalk</td>
                        <td>San Marino</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>ST</td>
                        <td>
        

        
        
        

        

        🇸🇹
    </td>
                        <td>SmallTalk, Structured Text</td>
                        <td>Sao Tome and Principe</td>
                    </tr>
                
                    
                    
                    

                    <tr>
                        <td>SV</td>
                        <td>
        

        
        
        

        

        🇸🇻
    </td>
                        <td>SystemVerilog</td>
                        <td>El Salvador</td>
                    </tr>
                
            </tbody>
        </table>
    </div>


                ]]></content></entry><entry><title>Not everything is on the Internet</title><summary>Sometimes, looking harder isn't enough.</summary><updated>2024-05-06T00:00:00Z</updated><id>https://www.bruh.ltd/blog/not-everything-is-on-the-internet/</id><link rel="alternate" href="https://www.bruh.ltd/blog/not-everything-is-on-the-internet/"/><content type="html"><![CDATA[
                    <p>When I was a kid, my father used to always tell me &quot;Everything is on
the Internet! Just look harder!&quot; Over the years, I've come to realize
that this was bullshit.</p>
<p>Sometimes, it isn't on the Internet:</p>
<ul>
<li>Because your question is so hard, that science doesn't yet have a
good answer to it.</li>
<li>Because you're looking for something so specific and
inconsequential, that no one's simply bothered to deal with it yet.</li>
<li>Because you're looking for something that shouldn't exist, guided by
a fundamental misunderstanding in your research.</li>
<li>Because whoever made it lived a long time ago, and their work didn't
survive.</li>
<li>Because no one preserved it while it was on the Internet.</li>
<li>Because whoever made it isn't on the Internet. Yes, such people
<a href="https://en.wikipedia.org/wiki/List_of_countries_by_number_of_Internet_users">still exist</a>.</li>
<li>Because whoever made it thought it was too trivial to share.</li>
<li>Because it's only somewhere in a book no one's put on the Internet
yet.</li>
<li>Because something close to it is. Too bad it isn't a perfect
substitute.</li>
</ul>
<p>Or sometimes, it is on the Internet:</p>
<ul>
<li>But only in someone's private archive.</li>
<li>But not indexed by search engines at all.</li>
<li>But will soon no longer be because whoever is responsible stopped
caring.</li>
<li>But impossible to find due to being drowned by endless amounts of
SEO slop.</li>
<li>But behind a paywall you can't climb over.</li>
<li>But not in your country.</li>
<li>But unusable on your hardware/software.</li>
<li>But doesn't accommodate your disability.</li>
<li>But not in a form you understand.</li>
<li>But it fucking sucks.</li>
<li>But not all in one place.</li>
</ul>
<p>And sometimes, you have a genuine original thought.</p>
<p>Don't let the notion of the Internet being a vast sea with everything
in it stop you from sharing — it's not even true.</p>

                ]]></content></entry><entry><title>Diagnose me</title><summary>I can't afford a therapist.</summary><updated>2024-05-05T00:00:00Z</updated><id>https://www.bruh.ltd/blog/diagnose-me/</id><link rel="alternate" href="https://www.bruh.ltd/blog/diagnose-me/"/><content type="html"><![CDATA[
                    <p>Long story short: I live in a country with an utterly dysfunctional
healthcare system. I can't afford a private therapist, and public
healthcare has been worse than useless. The following is my (another)
attempt at making a list of things that impair my day-to-day
existence, not in any particular order. I'm doing it mostly to just
catalog them, but I also hope it'll let me crowdsource more coping
techniques from people dealing with the same issues.</p>











<hgroup>
    <h2 id="social-life">
        Social life
    </h2>

    <a href="#social-life" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Social life'</span>
    </a>
</hgroup>



<ul>
<li>A wide range of people telling me that I &quot;act weird&quot;.</li>
<li>Struggling with expressing my thoughts, especially when not given an
opportunity to write everything down in advance.</li>
<li>Taking a long time to adapt to a new group of people.</li>
<li>Being scared shitless of interacting with people for the first time,
even if it's something inconsequential like posting online.</li>
<li>Revealing too many details about my private life after I've adapted.</li>
<li>Struggling with eye contact.</li>
</ul>











<hgroup>
    <h2 id="emotional-regulation">
        Emotional regulation
    </h2>

    <a href="#emotional-regulation" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Emotional regulation'</span>
    </a>
</hgroup>



<ul>
<li>Getting upset to the point of a mental breakdown when suddenly
reminded of a currently worrying topic.</li>
<li>Recalling negative events related to that topic and getting angry
that I let them happen.</li>
<li>Punching myself, usually in the thighs, sometimes causing bruises,
to stop myself from recalling them.</li>
</ul>











<hgroup>
    <h2 id="irrational-fears">
        Irrational fears
    </h2>

    <a href="#irrational-fears" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Irrational fears'</span>
    </a>
</hgroup>



<ul>
<li>Punishing myself for merely thinking of something bad, like
performing an act of extreme violence, &quot;because if I don't make it
stop, it'll get worse&quot; or &quot;because I'm not a bad person, and I need
to prove it to myself&quot;.</li>
<li>Blowing a minor setback, like a health issue, out of proportion
&quot;because what if it's more serious than it looks&quot; and thinking
through every unrealistic way it could result in my slow and painful
death.</li>
<li>Punishing myself for doing nothing about that setback &quot;because I'm
responsible for it, so I have to do something&quot; when there's nothing
that can be done about it anymore.</li>
<li>Punishing myself for doing something which makes sense right now but
which would probably look awkward if someone else was around
&quot;because what if someone notices it somehow&quot; when there's no good
reason to suspect that.</li>
</ul>











<hgroup>
    <h2 id="productivity">
        Productivity
    </h2>

    <a href="#productivity" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Productivity'</span>
    </a>
</hgroup>



<ul>
<li>Complete lack of motivation by things that I'm not currently
obsessed over, even when they're crucial for survival.</li>
<li>Getting stuck and not being able to think of what to do when finally
trying to start doing something.</li>
<li>Spending too much time trying to come up with all possible failure
options &quot;because what if I haven't thought it through well enough,
and I'm gonna make another stupid mistake that can be prevented
right now&quot;.</li>
<li>Spending too much time trying to find out whether I should be doing
tasks in this specific order &quot;because what if I'm wasting my time
when I could be doing something more important first&quot;.</li>
</ul>











<hgroup>
    <h2 id="avoidance-of-responsibility">
        Avoidance of responsibility
    </h2>

    <a href="#avoidance-of-responsibility" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Avoidance of responsibility'</span>
    </a>
</hgroup>



<ul>
<li>Not doing difficult tasks when I absolutely should, even at the cost
of catastrophic failure, &quot;so I don't have to deal with the
consequences of fucking up&quot; or &quot;because I'm worthless and I
shouldn't bother trying&quot;.</li>
<li>Trying to find any excuse to stop doing the task after having
already started &quot;because I'll fuck it up in the end, and it's better
to give up now&quot; or &quot;because it's not worth doing anyway&quot;.</li>
<li>Asking for help and making up bullshit excuses to avoid doing
anything &quot;because I deserve to suffer&quot; or &quot;because I want to give
up&quot;.</li>
<li>Postponing tasks for way too long, regardless of how little effort
they require, &quot;because they require doing something&quot;.</li>
<li>Refusing to do anything meaningful when completely bored &quot;because I
want to keep wasting time&quot; while still constantly thinking about it.</li>
</ul>











<hgroup>
    <h2 id="repetitive-behaviors">
        Repetitive behaviors
    </h2>

    <a href="#repetitive-behaviors" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Repetitive behaviors'</span>
    </a>
</hgroup>



<ul>
<li>(Childhood) Knocking on things a certain number of times &quot;or I'm
going to die&quot;.</li>
<li>(Circa 2022) Pretending I don't know something in order to trick
people into explaining it to me &quot;to see if they actually know about
it&quot; or &quot;to find new information about it without making an awkward
question&quot;.</li>
<li>(Semi-ongoing) Trying to suppress invasive thoughts by either
ridiculing them or thinking something worse. Makes the thoughts stay
for even longer.</li>
<li>(Semi-ongoing) Repeating my todo list for today in my head over and
over &quot;or I'm going to forget to do something again&quot;.</li>
<li>(Semi-ongoing) Purposefully involving myself in arguments with
idiots online or imagining arguments with an exaggerated version of
them that dodges all attempts at reasoning &quot;because they're wrong
and I need to always be ready to debate them&quot;.</li>
<li>(Ongoing) Checking something way more times than necessary,
particularly when it's not obvious whether it's true (e.g. &quot;is this
photo blurry?&quot;), &quot;so I know it for certain&quot; or &quot;so I'm sure I'm not
making it up&quot;.</li>
<li>(Ongoing) Obsessing over whether I really like a certain piece of
media and avoiding it &quot;so I don't get tired of it&quot; or purposefully
subjecting myself to it more times than necessary &quot;so people don't
think I'm a poser&quot;. Causes me to develop a negative association with
that piece of media, even though I like it, which fucks with my
brain.</li>
<li>(Ongoing) Reading things I'd written to someone over and over
&quot;because I did a such good job phrasing them&quot;.</li>
<li>(Very ongoing) Listening to the same song on repeat for hours.</li>
<li>Random fidgeting, like tapping or beatboxing, that pops out once in
a while but which doesn't take so much time as to be harmful.</li>
</ul>

                ]]></content></entry><entry><title>Archetypes of website navigation</title><summary>Hopefully an exhaustive classification.</summary><updated>2024-02-28T00:00:00Z</updated><id>https://www.bruh.ltd/blog/archetypes-of-website-navigation/</id><link rel="alternate" href="https://www.bruh.ltd/blog/archetypes-of-website-navigation/"/><content type="html"><![CDATA[
                    <p>This article is my attempt at classifying different basic types of
website navigation according to my observations. I know there's a
million posts written about it already, but I don't like them.</p>











<hgroup>
    <h2 id="what-this-article-isn-t-about">
        What this article isn't about
    </h2>

    <a href="#what-this-article-isn-t-about" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'What this article isn't about'</span>
    </a>
</hgroup>



<p>It isn't about website &quot;structure&quot;. No attention will be paid to what
a webmaster thinks their website is structured like. Only how a user
moves between pages will be considered.</p>
<p>It isn't about in-text hyperlinks. Every website has those — it's the
main feature of the Web. My definition of &quot;navigation&quot; will be limited
to strictly lists of links that serve no purpose other than guiding
the user.</p>
<p>It isn't a prescription on which type you should use in which
situation. You can use any. Don't let a random blog post stop you from
exploring your creativity.</p>
<p>It isn't about &quot;search engine optimization&quot;. If you think SEO is a
good thing, knowing full well the extent of the damage it's done to
the Web, you should seriously reconsider your life choices.</p>
<p>Now that I pissed off the only people who'd be interested in reading
this, let's cut to the chase.</p>











<hgroup>
    <h2 id="the-archetypes">
        The archetypes
    </h2>

    <a href="#the-archetypes" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'The archetypes'</span>
    </a>
</hgroup>



<p>Not in any particular order.</p>











<hgroup>
    <h3 id="comb">
        Comb
    </h3>

    <a href="#comb" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Comb'</span>
    </a>
</hgroup>





<figure >
    
    

    
    <picture>
        <img
            src="/blog/archetypes-of-website-navigation/comb.png"
            alt="Homepage connected to a few pages, the rest is mystery"

            width="256"
            height="256"
        >
    </picture>

    
</figure>

<p>This is the most straightforward type and one of the easiest to
implement — it requires little effort as long as you have any template
engine. You put a bunch of links to the most important places on every
single page, usually in the header, and that's it. If you want to go
somewhere less important, you deal with it somehow™, usually by
resorting to a different navigation type for a specific section.</p>
<p>Due to being the first thing anyone thinks when hearing the word
&quot;navigation&quot;, it's hard to give an example of where exactly it's used.
Let's just say it's used pretty much everywhere.</p>











<hgroup>
    <h3 id="tree">
        Tree
    </h3>

    <a href="#tree" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Tree'</span>
    </a>
</hgroup>





<figure >
    
    

    
    <picture>
        <img
            src="/blog/archetypes-of-website-navigation/tree.png"
            alt="Pages arranged in a binary tree with the homepage on top"

            width="256"
            height="256"
        >
    </picture>

    
</figure>

<p>In this type, pages represent nodes in a hierarchy. Like with an
actual tree, navigation is done by descending to a child or ascending
to a parent, except you do it with links and not by scraping your ass
against the bark. Descent is implemented as a list of children pages,
and ascent can be implemented either as a &quot;go up&quot; link or as
breadcrumbs, depending on how much effort you want to put into it.</p>
<p>As you can tell, this is some weird computer sciency shit that doesn't
reflect how normal people organize stuff. For this reason, it's
vanishingly rare to see it used for an entire website. It's also,
however, the perfect way to represent a filesystem on the Web, which
is why it's used in many file directories and indices. And this
website too for some reason.</p>











<hgroup>
    <h3 id="hairbrush">
        Hairbrush
    </h3>

    <a href="#hairbrush" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Hairbrush'</span>
    </a>
</hgroup>





<figure >
    
    

    
    <picture>
        <img
            src="/blog/archetypes-of-website-navigation/hairbrush.png"
            alt="Page with a sidebar displaying a connection hierarchy"

            width="256"
            height="256"
        >
    </picture>

    
</figure>

<p>As the name suggests (or so I hope), this is a combination of the
previous 2 types. There's still a hierarchy, but instead of pages only
having links to their neighbors, they have an entire copy of the
hierarchy. Since hierarchies take a lot of space, the links are almost
always put in a sidebar, or a header but in a collapsed form.</p>
<p>A typical consumer of this type nowadays is documentation websites,
which makes sense because it lets you jump between lots of topics
while staying organized. Another place you could've encountered it in
is many websites from the late 2000s. They specifically used the
&quot;collapsed links in the header&quot; variety which fell out of use, likely
as it's unusable on smartphones.</p>











<hgroup>
    <h3 id="spawnpoint">
        Spawnpoint
    </h3>

    <a href="#spawnpoint" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Spawnpoint'</span>
    </a>
</hgroup>





<figure >
    
    

    
    <picture>
        <img
            src="/blog/archetypes-of-website-navigation/spawnpoint.png"
            alt="Homepage surrounded by pages, all connecting directly to it"

            width="256"
            height="256"
        >
    </picture>

    
</figure>

<p>You can consider this one a subtype of the comb navigation where the
number of important places is 1. The place in question being, of
course, the homepage which contains a map of everything there is on
the website. Return to the homepage is implemented as a simple &quot;go
home&quot; link unless you're applying it to an existing template made for
comb navigation, in which case you end up with an ugly header with a
single menu item.</p>
<p>Since you don't need a template engine to implement this type, it's
used on a lot of personal websites, especially ones hosted on fully
static providers like Neocities. It was common in the '90s as well,
for the same reason, among people who didn't want to use frames.</p>











<hgroup>
    <h3 id="rabbit-hole">
        Rabbit hole
    </h3>

    <a href="#rabbit-hole" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Rabbit hole'</span>
    </a>
</hgroup>





<figure >
    
    

    
    <picture>
        <img
            src="/blog/archetypes-of-website-navigation/rabbit-hole.png"
            alt="Pages randomly thrown around without any connections"

            width="256"
            height="256"
        >
    </picture>

    
</figure>

<p>This type can be summarized as &quot;no navigation&quot;. There are only in-text
hyperlinks, no dedicated navigation sections. As such, you don't
&quot;navigate&quot; it, you instead either search or open a funny article like
<a href="https://en.wikipedia.org/wiki/23_skidoo_(phrase)">23 skidoo</a>, start clicking on related terms, and then 5 hours later,
realize you dug all the way down to <a href="https://en.wikipedia.org/wiki/Flashbulb_memory">flashbulb memory</a>,
<a href="https://en.wikipedia.org/wiki/Arche-writing">arche-writing</a>, and <a href="https://en.wikipedia.org/wiki/Pseudo-Kufic">pseudo-Kufic</a> in 3 separate tabs.</p>
<p>Most wikis and some note taking/personal knowledge base websites use
this type. Completely understandable because trying to force a single
hierarchy of any sort onto hundreds or thousands of pages generally
doesn't end up well. It's additionally not totally uncommon to see it
on indie websites, especially artsy ones.</p>











<hgroup>
    <h3 id="ladder">
        Ladder
    </h3>

    <a href="#ladder" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Ladder'</span>
    </a>
</hgroup>





<figure >
    
    

    
    <picture>
        <img
            src="/blog/archetypes-of-website-navigation/ladder.png"
            alt="Chain of pages with the homepage on the bottom"

            width="256"
            height="256"
        >
    </picture>

    
</figure>

<p>The most limiting type. The pages are arranged sequentially and shown
one at a time, with an action required to progress to the next one.
That action can be anything from swiping to pretending to be
neurotypical so you can get your minimal wage job from a company that
really wants to know your personality type. Most of the time, you can
go back to the previous page with another action.</p>
<p>TikTok and similar microvlogging (not to be confused with
microblogging) platforms use this type to fuel your addiction to
Family Guy clips. It's also the go-to for quizzes and authorization
forms, but can you truly call these last 2 examples &quot;navigation&quot;? I
don't know.</p>











<hgroup>
    <h3 id="meat-grinder">
        Meat grinder
    </h3>

    <a href="#meat-grinder" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Meat grinder'</span>
    </a>
</hgroup>





<figure >
    
    

    
    <picture>
        <img
            src="/blog/archetypes-of-website-navigation/meat-grinder.png"
            alt="Pages being displayed directly on the homepage"

            width="256"
            height="256"
        >
    </picture>

    
</figure>

<p>This one also involves no actual navigation, but this time, due to the
thing you're looking for already being right there in your face. The
pages, if you can still call them that, are all embedded into a single
page and seamlessly scrolled through by the user. Like a literal meat
grinder, it keeps on working forever as long as you have the meat.
Computers and infinities don't mix though, so &quot;forever&quot; is faked with
endless scrolling or good ol' pagination.</p>
<p>Image-oriented social media and microblogging platforms, most notably
Reddit and the no longer existent Twitter, (ab)use this type
extensively. This is the only example needed here as their sheer mass
alone accounts for most of the Web.</p>











<hgroup>
    <h2 id="conclusion">
        Conclusion
    </h2>

    <a href="#conclusion" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Conclusion'</span>
    </a>
</hgroup>



<p>Something I missed? Your thoughts are welcome.</p>

                ]]></content></entry><entry><title>Best purchases I've ever made</title><summary>Turns out little things do matter.</summary><updated>2024-02-20T00:00:00Z</updated><id>https://www.bruh.ltd/blog/best-purchases-ive-ever-made/</id><link rel="alternate" href="https://www.bruh.ltd/blog/best-purchases-ive-ever-made/"/><content type="html"><![CDATA[
                    <p>Some of them are gifts, not purchases, but that wouldn't make as
catchy a title. Either way, they sure are the best.</p>











<hgroup>
    <h2 id="4k-monitor">
        4K monitor
    </h2>

    <a href="#4k-monitor" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled '4K monitor'</span>
    </a>
</hgroup>



<p>Videos and video games aside, the thing that truly sells 4K to me is
fonts. This glyph rendering is incredible. No amount of antialiasing
or bullshit like subpixel rendering can compare to having 4 times as
many pixels. Considering I can't tell those pixels apart, this
resolution is comparable to printed books for me — something people in
the '80s could only dream of when they conceived the idea of WYSIWYG.
Needless to say, I'm not going back.</p>











<hgroup>
    <h2 id="epilator">
        Epilator
    </h2>

    <a href="#epilator" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Epilator'</span>
    </a>
</hgroup>



<p>My legs have been cursed with thick and dense hair that's impossible
to shave. You can try, but it regrows in a matter of literal hours,
turning into an irritated bloody mess in the process. I've always
suspected that an epilator could fix this, and guess what, I was
right. It absolutely did — it takes the hair a couple weeks, not
hours, to regrow now, and even then it's not as thick.</p>
<p>If you're thinking about buying yourself one, here are some tips:
First of all, yes it is painful, but it gets less painful when hair is
not as dense. Unless you wait, like, a month for it to regrow
completely, your second time won't be nearly as painful. For your
first time, the trick is to go <em>slowly</em>, as slow as you can, and put
up with the unbearable pain. It may take forever, but going one row of
hairs at a time is better than experiencing pain that's even less
bearable.</p>











<hgroup>
    <h2 id="fingerless-gloves">
        Fingerless gloves
    </h2>

    <a href="#fingerless-gloves" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Fingerless gloves'</span>
    </a>
</hgroup>



<p>I hate wearing gloves. They limit my fine motor skills, so I have to
either constantly take them off or suffer each time I want to take my
keys or money out of the pocket. They also don't work with
touchscreens, and I know I'm not supposed to use my phone while
walking, especially when it's cold outside, but fuck you, I'm gonna do
it anyway.</p>
<p>My hands hate the cold. Every time the temperature drops below, like,
10°C, they turn into a red dry desert that only spreads farther and
gets drier and redder the more I go outside. When it gets real bad,
they start bleeding. The problem doesn't completely go away until it's
warm outside again, no matter how much moisturizer I use.</p>
<p>Did I, at some point, consider these facts, accept that wearing gloves
is a necessity for survival, and go on with my life? No, of course
not. Instead, I did nothing up until this year when I realized that
fingerless gloves have none of the issues of regular gloves and are
almost as good at keeping my hands warm. Once in a while, being a
stubborn idiot has its upsides.</p>











<hgroup>
    <h2 id="kitchen-scale">
        Kitchen scale
    </h2>

    <a href="#kitchen-scale" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Kitchen scale'</span>
    </a>
</hgroup>



<p>I've recently gotten into cooking, and having a scale has been a
lifesaver, even more so than measuring spoons or a measuring cup. I'm
notoriously bad at eyeballing things, so if I don't have a concrete
measurement of something, I can and do mess it up. But not anymore —
my inconsistent hands now manage to consistently make identical pizza
dough each time I try. All I needed was a mass produced piece of
equipment you can buy for $5 and actually bothering to write down the
recipes.</p>











<hgroup>
    <h2 id="microwave">
        Microwave
    </h2>

    <a href="#microwave" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Microwave'</span>
    </a>
</hgroup>



<p>I grew up in a household without a microwave. I don't know why we
didn't have one because it's an awesome tool for reheating and
unfreezing food. Additionally, it's more reliable and requires a lot
less effort when it comes to boiling macaroni and grains, which is a
good thing because I'm really lazy. It's a shame it took me so long to
discover that, but at least I know why I shouldn't repeat my parents'
mistake.</p>











<hgroup>
    <h2 id="reusable-shopping-bag">
        Reusable shopping bag
    </h2>

    <a href="#reusable-shopping-bag" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Reusable shopping bag'</span>
    </a>
</hgroup>



<p>Plastic bags suck. They're harmful for the environment, cost a lot of
money to buy each time you go shopping, and are practically not
reusable. You use them a couple times, and they already start falling
apart. You can use them as glorified trash bags, I guess, if you don't
mind the price, but why would you? I wish I'd been asked this question
before because it took me way too long to realize that I could buy a
real shopping bag, made out of cloth, and forget about ever dealing
with plastic bags again.</p>











<hgroup>
    <h2 id="plastic-bathroom-drawer">
        Plastic bathroom drawer
    </h2>

    <a href="#plastic-bathroom-drawer" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Plastic bathroom drawer'</span>
    </a>
</hgroup>



<p>Okay, that's a weird one. I understand this is a very specific problem
that most people likely don't have, but I struggle with doing things
that don't have one obvious order of steps. One of these things is my
morning routine.</p>
<p>I've tried hard to stick to a specific order but couldn't until I
bought a plastic storage thingy with 3 drawers in it. I put the stuff
I need for brushing my teeth on the top, the stuff I need for shaving
in the middle, the stuff I need for skincare on the bottom, and the
whole thing in my bathroom. The issue is no more — I go from top to
bottom, no thinking required.</p>











<hgroup>
    <h2 id="scarf">
        Scarf
    </h2>

    <a href="#scarf" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Scarf'</span>
    </a>
</hgroup>



<p>This is a story similar to the one with gloves. I have an utterly
dysfunctional immune system, so I get sick all the time. Does this
mean I've always worn a scarf to protect my neck and not get sick even
more often? Nope! Not only did I not learn how to wear one, I'd never
bothered to get one in the first place until last year. Sometimes, I'm
surprised that I'm still alive in spite of my recklessness.</p>











<hgroup>
    <h2 id="xiaomi-redmi-note-8">
        Xiaomi Redmi Note 8
    </h2>

    <a href="#xiaomi-redmi-note-8" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Xiaomi Redmi Note 8'</span>
    </a>
</hgroup>



<p>Before we get to the praise, there's one thing you need to keep in
mind: Xiaomi is not your friend. It's a company whose primary business
is selling you a shitty Android reskin with an <a href="https://www.androidauthority.com/xiaomi-privacy-cheap-phone-1118444/">extensive history of
spyware</a> built into it, that they don't want you to get rid of, making
you <a href="https://new.c.mi.com/global/post/101245">jump through hoops</a> of <a href="https://9to5google.com/2023/11/08/xiaomi-android-hyperos-updates-bootloader-policy/">increasing insanity</a> to unlock the
bootloader and <a href="https://xiaomiui.net/xiaomi-violates-gpl-licenses-45443/">taking their sweet fucking time</a> to release the kernel
source code and comply with GNU GPL.</p>
<p>With that said however, their hardware is pretty damn good for its
price. My Redmi Note 8 was $150 when I bought it, and it's been the
most reliable phone I've ever had so far. There's a rich custom ROM
ecosystem, so I'm able to run a somewhat maintained copy of Android
14, with all of the useless crap cut out, even though it's been 5
years since the initial release.</p>
<p>It's also worth pointing out that the camera in this phone is
outstanding — as long as you disable edge enhancement, which you
should as it's the worst thing that's ever happened to photography, it
performs as well as early 2000s digital camera, except it fits in your
pocket and can record video in a non-potato resolution. The battery is
just as great and lasts long enough for it not to be annoying. That is
unless your ROM gets a mysterious battery drain issue which has
happened to me once.</p>

                ]]></content></entry><entry><title>88x31 buttons I've made</title><summary>And how they changed over time.</summary><updated>2024-02-13T00:00:00Z</updated><id>https://www.bruh.ltd/blog/88x31-buttons-ive-made/</id><link rel="alternate" href="https://www.bruh.ltd/blog/88x31-buttons-ive-made/"/><content type="html"><![CDATA[
                    <p>As I found out a while ago, some of the 88x31 buttons I've created
have made their way into online button collections, ending up on a
surprising number of indie websites. For future reference, here's a
complete list of them, detailing how I created them and how they
evolved over time:</p>
<p>(Okay, technically, this isn't a complete list because there's a bunch
of iterations where I didn't do anything except recompressing the
images or renaming them, but why would want to know about those?)</p>











<hgroup>
    <h2 id="initial-design">
        Initial design
    </h2>

    <a href="#initial-design" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Initial design'</span>
    </a>
</hgroup>



<p class="subtitle">
    <span class="visually-hidden">Date:</span> 2020-02-29
</p>



<figure >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2020-02-29-fbaac0.png"
            alt="Solid pink rectangle"

            width="88"
            height="31"
        >
    </picture>

    
        <figcaption>fbaac0.png</figcaption>
    
</figure>

<p>My social media profile picture at that moment was a solid square of
<a href="https://colornames.org/color/fbaac0">Slapper Pink</a>, my favorite color. Since I'm a very original person, I
did the same to the button for my website.</p>


<figure >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2020-02-29-neocities.png"
            alt="Fake &#39;NeoCities&#39; logo in front of a dim planet with rings"

            width="88"
            height="31"
        >
    </picture>

    
        <figcaption>neocities.png</figcaption>
    
</figure>

<p>This was my attempt at ripping off the <a href="https://anlucas.neocities.org/neocities_button.gif">Neocities.org, the web is
yours</a> button. I think I did a decent enough job because no one
noticed.</p>
<p>The font is Liberation Serif Bold Italic. The planet in the background
was taken from <a href="https://publicdomainvectors.org/en/free-clipart/Vector-clip-art-of-planet-Saturn-icon/21340.html">Public Domain Vectors</a>. If I remember correctly, the
space behind the planet is a heavily downscaled version of <a href="https://commons.wikimedia.org/wiki/File:Phoenix_dwarf_galaxy.jpg">that
picture from NASA</a> I used in my dream journal.</p>


<figure >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2020-02-29-www.png"
            alt="Shiny drawing of the Earth, captioned &#39;World Wide Web&#39;"

            width="88"
            height="31"
        >
    </picture>

    
        <figcaption>www.png</figcaption>
    
</figure>

<p>This was an attempt at ripping off <a href="https://anlucas.neocities.org/wwwbutton.gif">another button</a>, coincidentally
also made by A.N. Lucas. In retrospect, I did a shitty job. This looks
nothing but cheesy.</p>
<p>The picture of the planet was, once again, taken from <a href="https://publicdomainvectors.org/en/free-clipart/World-globe-vector-illustration/13075.html">Public Domain
Vectors</a>. The font is GNU Unifont.</p>


<figure >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2020-02-29-gnu-linux.png"
            alt="Fat penguin Tux, captioned &#39;Made on GNU/Linux&#39;"

            width="88"
            height="31"
        >
    </picture>

    
        <figcaption>gnu-linux.png</figcaption>
    
</figure>

<p>In the '90s, there were many buttons like &quot;Made with Notepad&quot;, so I
decided to make a parody of that with the software I used. I think I
got the motivation to do that from a button that said something like
&quot;Best viewed in Firefox&quot;.</p>
<p>The Tux was, of course, taken directly from <a href="http://www.isc.tamu.edu/~lewing/linux">Larry Ewing</a>. The font on
the top is GNU Unifont, and the one on the bottom is Liberation Serif
Bold Italic.</p>


<figure >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2020-02-29-neovim.png"
            alt="Sharp green letter N, captioned &#39;Made with neovim&#39;"

            width="88"
            height="31"
        >
    </picture>

    
        <figcaption>neovim.png</figcaption>
    
</figure>

<p>Same thing as with the GNU/Linux one.</p>
<p>The logo was taken directly off the website of <a href="https://neovim.io/">Neovim</a>. The font on
the top is, once again, GNU Unifont, and the one on the bottom is
Nimbus Roman Italic, half of which is bold. I used the same colors for
it as they did on the website.</p>
<hr>
<p>Without going too deep into the history of my website: on this date, I
decided to make an alternative retro-looking version on my website and
upload it to Neocities. As part of that effort, I decided to add some
buttons for extra points. A lot has changed since then, and now the
&quot;retro version&quot; is the only version of my website, and the Neocities
version is simply a mirror.</p>
<p>Like with every other artwork on this website, I used GIMP as my image
editing software and made heavy use of the nearest-neighbor
downscaling because that's what they did in the '90s too.
Additionally, I used no font antialising because that was completely
unheard of back then.</p>
<p>Since I'm a fancy fellow, I drew the borders with the NeXTSTEP/Windows
98 palette with 2 colors on each side instead of the one with 1 color
on each side, which almost every genuine '90s button used.
Unfortunately, this ended up biting me in the ass later because, guess
what, they did it for a reason — these colors are not <a href="https://en.wikipedia.org/wiki/Web_colors#Web-safe_colors">Web-safe</a>.</p>











<hgroup>
    <h2 id="-make-it-look-more-genuine-">
        &quot;Make it look more genuine&quot;
    </h2>

    <a href="#-make-it-look-more-genuine-" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled '&quot;Make it look more genuine&quot;'</span>
    </a>
</hgroup>



<p class="subtitle">
    <span class="visually-hidden">Date:</span> 2020-03-01
</p>



<figure  aria-hidden="true" >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2020-03-01-fbaac0.gif"
            alt=""

            width="88"
            height="31"
        >
    </picture>

    
</figure>



<figure  aria-hidden="true" >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2020-03-01-neocities.gif"
            alt=""

            width="88"
            height="31"
        >
    </picture>

    
</figure>



<figure  aria-hidden="true" >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2020-03-01-www.gif"
            alt=""

            width="88"
            height="31"
        >
    </picture>

    
</figure>



<figure  aria-hidden="true" >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2020-03-01-gnu-linux.gif"
            alt=""

            width="88"
            height="31"
        >
    </picture>

    
</figure>



<figure  aria-hidden="true" >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2020-03-01-neovim.gif"
            alt=""

            width="88"
            height="31"
        >
    </picture>

    
</figure>

<p>Oh boy, that's a weird one. So first of all, your eyes aren't
deceiving you — there were no visual changes in this iteration. Or
well, I guess your ears if you're using a screen reader. Either way,
the only change was that I converted everything to GIF (pronounced
&quot;GIF&quot;) so when people download them, they see the .gif extension and
think &quot;ah yes, a genuine '90s website&quot;. I abandoned this idea 6 days
later because, you know, fuck it, PNG is fine.</p>
<p>Initially, I was going to write that this was, perplexingly, the
iteration that spread, despite being the shortest living one, but it
seems actually not to be the case. The only clue I have as to why any
of them spread at all is <a href="https://web.archive.org/web/20210204133118/https://cyber.dabamos.de/88x31/index2.html">this button wall</a> which picked up the
GNU/Linux button sometime between 2020 and 2021. My theory before was
that since it has a .gif extension on that wall, its author/their
scanner must've picked the button from my website when it was still in
GIF. But now that I look at it, the button on that wall ain't the
2020-03-01 iteration, it's the 2020-03-07 iteration. Did it end up
there for some other reason, and the .gif extension is just a
byproduct of a conversion the author of the wall did? I'm even more
clueless now than before.</p>
<p>But regardless, by sheer luck, the GNU/Linux button, presumably
downloaded from that wall, ended up in a <a href="https://www.youtube.com/watch?v=tqydVNaLR1w&amp;t=641">video by Michael MJD</a>. Truly
a surreal experience.</p>











<hgroup>
    <h2 id="and-now-it-s-web-safe™">
        And now it's Web-safe™
    </h2>

    <a href="#and-now-it-s-web-safe%e2%84%a2" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'And now it's Web-safe™'</span>
    </a>
</hgroup>



<p class="subtitle">
    <span class="visually-hidden">Date:</span> 2020-03-07
</p>



<figure  aria-hidden="true" >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2020-03-07-fbaac0.png"
            alt=""

            width="88"
            height="31"
        >
    </picture>

    
</figure>



<figure  aria-hidden="true" >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2020-03-07-neocities.png"
            alt=""

            width="88"
            height="31"
        >
    </picture>

    
</figure>



<figure  aria-hidden="true" >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2020-03-07-www.png"
            alt=""

            width="88"
            height="31"
        >
    </picture>

    
</figure>



<figure  aria-hidden="true" >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2020-03-07-gnu-linux.png"
            alt=""

            width="88"
            height="31"
        >
    </picture>

    
</figure>



<figure  aria-hidden="true" >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2020-03-07-neovim.png"
            alt=""

            width="88"
            height="31"
        >
    </picture>

    
</figure>

<p>The main difference in this iteration is, as you've probably guessed
already, the fact that I switched from using an automatically
generated, for each button, palette to a 216 color Web-safe palette
because that's more authentic. The fancy borders had to be sacrificed
in the process. I used Floyd-Steinberg dithering because, while I was
experimenting with background images, it turned out ordered dithering
sucks really bad. Since the planet on World Wide Web button was
already dithered, I remastered it to use Floyd-Steinberg too so it
doesn't look out of place.</p>











<hgroup>
    <h2 id="slap-like-now-">
        Slap like NOW!
    </h2>

    <a href="#slap-like-now-" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Slap like NOW!'</span>
    </a>
</hgroup>



<p class="subtitle">
    <span class="visually-hidden">Date:</span> 2020-03-13
</p>



<figure >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2020-03-13-slap-like-now.png"
            alt="Thumbs up emoji, captioned &#39;Slap like NOW!&#39;"

            width="88"
            height="31"
        >
    </picture>

    
        <figcaption>slap-like-now.png</figcaption>
    
</figure>

<p>I think I added this one so there are 6 of them total and they all
align into one nice 2 row rectangle. In case you're wondering, it
linked to my Neocities profile page, and the phrase itself was stolen
from <a href="https://www.youtube.com/@Davie504">Davie504</a>. Also it's sort of a parody of the famous &quot;Netscape
Now!&quot; button.</p>
<p>The thumbs up emoji was stolen from <a href="https://github.com/twitter/twemoji/blob/master/assets/svg/1f44d.svg">Twemoji</a>. Unfortunately, by
&quot;stolen&quot; I actually mean stolen because I don't think I've ever
credited them for that on the licensing information page. Oh well, I
guess better late than never:</p>
<blockquote>
<p>Copyright 2019 Twitter, Inc and other contributors. Graphics
licensed under <a href="https://creativecommons.org/licenses/by/4.0/">CC-BY 4.0</a></p>
</blockquote>
<p>The fonts are the same as in the GNU/Linux and the Neovim buttons —
GNU Unifont on the top and Liberation Serif Bold Italic on the bottom.</p>











<hgroup>
    <h2 id="a-wild-folder-appears">
        A wild folder appears
    </h2>

    <a href="#a-wild-folder-appears" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'A wild folder appears'</span>
    </a>
</hgroup>



<p class="subtitle">
    <span class="visually-hidden">Date:</span> 2020-12-27
</p>



<figure >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2020-12-27-kirby.png"
            alt="Michaelsoft Bindows 1997 folder, captioned &#39;K.K.&#39;"

            width="88"
            height="31"
        >
    </picture>

    
        <figcaption>kirby.png</figcaption>
    
</figure>

<p>I got bored of using a solid color to represent myself, so I put the
initials I used back then near a folder icon and called it a day. The
folder, if that even requires an explanation, was inspired by Windows
95.</p>
<p>The font is Liberation Serif Bold Italic but a bit bigger.</p>











<hgroup>
    <h2 id="-kinda-">
        (kinda)
    </h2>

    <a href="#-kinda-" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled '(kinda)'</span>
    </a>
</hgroup>



<p class="subtitle">
    <span class="visually-hidden">Date:</span> 2021-12-09
</p>



<figure >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2021-12-09-neocities.png"
            alt="Same &#39;NeoCities&#39; but with &#39;(kinda)&#39; written under"

            width="88"
            height="31"
        >
    </picture>

    
</figure>

<p>The main version of my website had been moved from Neocities, but I
still used the latter as a mirror. In order not to accidentally
gaslight people into thinking it didn't happen, I wrote a &quot;(kinda)&quot;
under this button using the pencil tool. I could've done a better job
drawing the letters, but whatever, the idea was questionable anyway.</p>











<hgroup>
    <h2 id="folder-">
        Folder.
    </h2>

    <a href="#folder-" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Folder.'</span>
    </a>
</hgroup>



<p class="subtitle">
    <span class="visually-hidden">Date:</span> 2021-12-29
</p>



<figure >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2021-12-29-kirby.png"
            alt="Seemingly exactly the same folder. Or is it?"

            width="88"
            height="31"
        >
    </picture>

    
</figure>

<p>The shadow on top is shorter by 1 pixel. That's it, that's the
difference.</p>











<hgroup>
    <h2 id="🐻">
        🐻
    </h2>

    <a href="#%f0%9f%90%bb" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled '🐻'</span>
    </a>
</hgroup>



<p class="subtitle">
    <span class="visually-hidden">Date:</span> 2022-01-02
</p>



<figure >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2022-01-02-bruh-ltd.png"
            alt="Bear in front of portable toilets, captioned &#39;Bruh, Ltd&#39;"

            width="88"
            height="31"
        >
    </picture>

    
        <figcaption>bruh-ltd.png</figcaption>
    
</figure>

<p>I realized how ridiculous &quot;NeoCities (kinda)&quot; looked and replaced it
with a button I quickly made for Bruh, Ltd.</p>
<p>The bear was drawn by my friend in Paint.NET. Since nearest neighbor
downscaling ruined its eyes, I manually touched them up a bit. The
background image was taken from <a href="https://www.publicdomainpictures.net/en/view-image.php?image=298717&amp;picture=public-toilets">Public Domain Pictures</a>. I don't
remember what font I used, but it was probably either Liberation Sans
or Nimbus Sans.</p>











<hgroup>
    <h2 id="3-folders-1-day">
        3 folders, 1 day
    </h2>

    <a href="#3-folders-1-day" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled '3 folders, 1 day'</span>
    </a>
</hgroup>



<p class="subtitle">
    <span class="visually-hidden">Date:</span> 2022-04-21
</p>



<figure >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2022-04-21-kirby.png"
            alt="The folder is now gray and open and the background is darker"

            width="88"
            height="31"
        >
    </picture>

    
</figure>



<figure >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2022-04-21-kirby2.png"
            alt="Same folder but now pink"

            width="88"
            height="31"
        >
    </picture>

    
</figure>



<figure >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2022-04-21-kirby3.png"
            alt="Same folder, still pink, but something is off"

            width="88"
            height="31"
        >
    </picture>

    
</figure>

<p>I decided that a Windows 95 aesthetic was boring, so I started looking
for inspiration in Unix desktop environments, one of which was <a href="https://commons.wikimedia.org/wiki/File:GNOME_1.0_(1999,_03)_with_file_manager_application.gif">GNOME
1</a>. Then I realized this gray looks ugly and remembered that <a href="https://en.wikipedia.org/wiki/File:Mac_OS_8.1_emulated_inside_of_SheepShaver.png">Classic
MacOS</a> used purple as the accent color. My favorite color is pink, and
that's close to purple, so I connected the dots and made the folder
pink. Best decision I've ever made. It looks awesome.</p>
<p>By the way, the third version of the button is different — the folder
was moved to the right by 1 pixel. I also centered my profile picture
by using <a href="https://javier.xyz/visual-center">this awesome tool</a>. And yeah, the darker border is now
slightly pink too.</p>











<hgroup>
    <h2 id="the-great-rename">
        The Great Rename
    </h2>

    <a href="#the-great-rename" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'The Great Rename'</span>
    </a>
</hgroup>



<p class="subtitle">
    <span class="visually-hidden">Date:</span> 2022-09-10
</p>



<figure >
    
    

    
    <picture>
        <img
            src="/blog/88x31-buttons-ive-made/2022-09-10-yours-truly.png"
            alt="Same folder, but the caption is now &#39;Yours Truly&#39;"

            width="88"
            height="31"
        >
    </picture>

    
        <figcaption>yours-truly.png</figcaption>
    
</figure>

<p>My initials are no longer K.K., so here's that. Since my new name is
shorter, I made the home page layout narrower. 3 rows of buttons
looked way too big, so I got rid of the World Wide Web and the Slap
like NOW! buttons. Not a big loss, to be fair.</p>
<p>The phrase &quot;Yours truly&quot; was taken from the <a href="https://www.youtube.com/watch?v=5pvnqCbG71M">Super Mario 64 cutscene</a>
where Princess Peach invites Mario over to a dinner. I've never played
that game, but the scene looks really cool. I even used it as the
inspiration for my <a href="https://bruh.ltd/0032-email/">email page</a> which I eventually moved to Bruh, Ltd.</p>
<p>I drew the letters by myself because Comic Neue Italic didn't look
good at this resolution.</p>











<hgroup>
    <h2 id="conclusion">
        Conclusion
    </h2>

    <a href="#conclusion" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Conclusion'</span>
    </a>
</hgroup>



<p>If you see any of these buttons online, now you know what time
interval they initially came from.</p>

                ]]></content></entry><entry><title>Reg.ru sucks</title><summary>Don't give them your money.</summary><updated>2024-02-09T00:00:00Z</updated><id>https://www.bruh.ltd/blog/reg-ru-sucks/</id><link rel="alternate" href="https://www.bruh.ltd/blog/reg-ru-sucks/"/><content type="html"><![CDATA[
                    <p>The following is a recollection of things I went through while using
Reg.ru as my domain name registrar. Needless to say, none of them were
positive.</p>











<hgroup>
    <h2 id="account-registration">
        Account registration
    </h2>

    <a href="#account-registration" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Account registration'</span>
    </a>
</hgroup>



<p>There are 2 main issues with it, and my brain can't comprehend how
they can possibly happen at the same time:</p>
<p>First, they ask you to <a href="https://help.reg.ru/support/lichnyy-kabinet/registratsiya-i-kontaktnyye-dannyye/kontaktnyye-dannyye-vladeltsa-akkaunta">give them your passport data</a>. Yes, this is
not a joke. It's supposedly optional, but they really want you to do
it because they take away your ability to do a bunch of stuff like
withdrawing your money back or transferring account ownership if you
don't. This point will also become relevant later.</p>
<p>Second, there's <a href="https://help.reg.ru/support/lichnyy-kabinet/bezopasnost-akkaunta/dvukhfaktornaya-avtorizatsiya">no TOTP two-factor authentication</a>. The only option
is SMS-based two-factor authentication, using 4-digit codes if that
wasn't bad enough already. Not giving the user a choice to avoid SIM
swapping attacks is a pretty shitty thing to do, if you ask me,
especially when you're dealing with sensitive data.</p>











<hgroup>
    <h2 id="buying-transferring-a-domain-name">
        Buying/transferring a domain name
    </h2>

    <a href="#buying-transferring-a-domain-name" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Buying/transferring a domain name'</span>
    </a>
</hgroup>



<p>Before you enter your card credentials, you'll notice the elephant in
the room: everything is roughly twice as expensive as you'd expect.
Don't believe me? Let's compare the prices (transfer only, without the
discounts) at the time of writing:</p>
<p><a href="https://www.reg.ru/company/prices/domain">Reg.ru</a>
(the transfer/renewal price is only shown when you hover over a TLD):</p>
<ul>
<li>.com: $22.67</li>
<li>.online: $50.65</li>
<li>.zone: $63.20</li>
<li>.co: $71.85</li>
<li>.ru: $10.98</li>
</ul>
<p><a href="https://porkbun.com/products/domains">Porkbun</a>:</p>
<ul>
<li>.com: $10.37</li>
<li>.online: $26.24</li>
<li>.zone: $26.24</li>
<li>.co: $22.97</li>
<li>.ru: N/A</li>
</ul>
<p><a href="https://www.hover.com/domain-pricing">Hover</a>:</p>
<ul>
<li>.com: $17.99</li>
<li>.online: $34.99</li>
<li>.zone: $39.99</li>
<li>.co: $27.99</li>
<li>.ru: N/A</li>
</ul>
<p>So yeah, unless you want a .ru domain, this isn't good.</p>
<p>In addition to that, however, they <a href="https://help.reg.ru/support/domains/administrator-domena/skrytiye-personalnykh-dannykh-administratora-domena">charge you for WHOIS privacy</a> for
non-Russian domains. It's not much — $2.2 a year — but I can't
emphasize enough how fucking braindead this decision is in the modern
world. WHOIS privacy is absolutely essential for individual people, so
you don't have much choice. This is effectively a &quot;fuck you, give us
even more money&quot;.</p>
<p>Now, the last thing I want to point out here is sort of my fault.
Reg.ru apparently <a href="https://help.reg.ru/support/dns-servery-i-nastroyka-zony/dopolnitelnyye-vozmozhnosti/dnssec">doesn't support DNSSEC</a> for anything but a handful
of TLDs, and I forgot to disable it before transferring my domain name
to them, making my website stuck in a limbo. It took the support 4
days to resolve this, and the wait was infuriating, but oh well. I
guess now I know that this is an issue that can happen.</p>











<hgroup>
    <h2 id="unique-features">
        Unique features
    </h2>

    <a href="#unique-features" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Unique features'</span>
    </a>
</hgroup>



<p>There are none. They offer stuff unrelated to domain names, like VPSes
and website hosting, but virtually everyone offers these, so it's not
anything special. I myself haven't used any of them, so I won't
comment on it.</p>
<p>In terms of domain names, they offer exactly the same things as
everyone else, like a DNS server and paid <a href="https://www.reg.ru/ssl-certificate/">TLS certificates</a> that you
don't need because you can get them for free from <a href="https://letsencrypt.org/">Let's Encrypt</a>,
<a href="https://zerossl.com/">ZeroSSL</a>, or a million other places. Hilariously, they also offer
printed &quot;<a href="https://www.reg.ru/domain/service/certificate">domain ownership certificates</a>&quot; which, as far as I can tell,
serve zero useful purpose.</p>











<hgroup>
    <h2 id="leaving-for-another-registrar">
        Leaving for another registrar
    </h2>

    <a href="#leaving-for-another-registrar" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Leaving for another registrar'</span>
    </a>
</hgroup>



<p>If you ever decide that their service isn't worth your money, oh boy,
you're in for a treat. You can't just enable domain transfer and copy
the authinfo key. No-no, instead you have to <a href="https://help.reg.ru/support/domains/perenos-domena/perenos-domena-ot-reg-ru/perenos-mezhdunarodnogo-domena-ot-reg-ru-k-drugomu-registratoru">leave a request</a> to get
it emailed to you. Lost the email? Tough shit, now you have to wait a
month for your next attempt. Didn't get the email in the first place?
Guess what, you have to wait for them to &quot;process&quot; your request. They
don't specify how long it should take for international domains, but
for .ru it may take up to <a href="https://help.reg.ru/support/domains/perenos-domena/perenos-domena-ot-reg-ru/perenos-domena-v-zonakh-ru-i-rf-ot-reg-ru-k-drugomu-registratoru">3 motherfucking days</a>. For me, it took a
day.</p>
<p>But what if you don't want to transfer anything? Can you just
painlessly disown a domain? No, you have to contact the support and
<a href="https://help.reg.ru/support/domains/udaleniye-domena/udaleniye-domena-v-mezhdunarodnoy-zone">attach your passport data</a>. That's right, you can buy a domain
without giving them your passport but you can't get rid of it. How
convenient, you assholes! My eyes couldn't believe it when I
discovered that.</p>
<p>None of this should be necessary. It achieves nothing but making the
process of leaving them as tedious as possible so you don't bother and
pay up. This is the domain name equivalent of gym subscriptions that
you can buy online but can't cancel without several unholy rituals.</p>











<hgroup>
    <h2 id="then-they-try-to-silence-you">
        Then, they try to silence you
    </h2>

    <a href="#then-they-try-to-silence-you" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Then, they try to silence you'</span>
    </a>
</hgroup>



<p>On 2024-09-19, I was contacted by someone claiming to be a backlink
specialist for Internet companies. I don't know if they were a Reg.ru
employee, but judging by their question, I tend to believe they were:
They were asking if they could get a &quot;link on my blog&quot;, likely hinting
at a sponsored post, while asking about this post. No, you can't. I
have not and will not accept money or any other kind of favors to put
anything on my website.</p>
<p>Commercialization has already ruined the Web in the past 2 decades,
filling search results with slop generated by dishonest people
(sponsored posts), slop generated by people who value money over
everything else (&quot;search engine optimized&quot; posts), and recently, slop
generated by machines that can't think but can speak well enough to
imitate the other 2 groups (AI-generated posts). Regardless of how
well you're paid, your decision to contribute to complete erosion of
trust on the Internet is never admirable. You deserve better than
that. Go home and rethink your life.</p>











<hgroup>
    <h2 id="conclusion">
        Conclusion
    </h2>

    <a href="#conclusion" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Conclusion'</span>
    </a>
</hgroup>



<p>Reg.ru offers nothing that makes them worth it and treats you like a
money cow, not a customer. Don't buy from them.</p>

                ]]></content></entry><entry><title>Things no one told me about TCP/IP networking</title><summary>A quick dive into how everything works.</summary><updated>2024-01-08T00:00:00Z</updated><id>https://www.bruh.ltd/blog/things-no-one-told-me-about-tcp-ip-networking/</id><link rel="alternate" href="https://www.bruh.ltd/blog/things-no-one-told-me-about-tcp-ip-networking/"/><content type="html"><![CDATA[
                    <p>If you're a person with any experience in maintaining computer
networks, you probably won't learn anything new reading this article.
I myself am not a system administrator, and the following is merely my
best attempt at summarizing my knowledge without omitting some but not
all uncomfortable details. In other words, it's what I wish I was
given back in college because my curriculum did a really poor job. Be
warned: there can be factual errors.</p>











<hgroup>
    <h2 id="architectural-beauty-of-tcp-ip-and-the-osi-model-">
        Architectural beauty of TCP/IP and the &quot;OSI model&quot;
    </h2>

    <a href="#architectural-beauty-of-tcp-ip-and-the-osi-model-" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Architectural beauty of TCP/IP and the &quot;OSI model&quot;'</span>
    </a>
</hgroup>



<p>Let's say we have a few computers and we want to connect them together
to share information between them. Create a <strong>network</strong>, if you will.
In the history of computing, there have been countless ways to do it.
Smart people who developed them called these ways <strong>protocol suites</strong>.
Pretty much all of them are now dead, with the exception of <strong>TCP/IP</strong>
which is a fancy way of saying &quot;protocols that the Internet uses, 2 of
which are TCP and IP&quot;.</p>
<p>If we want to fully admire the beauty of these protocols, we need to
first understand their underlying principles that may not be that
obvious at a glance:</p>
<ul>
<li>Plug and play: For the most part, computers get along without
announcing their presence or being aware that anyone is present.
They send stuff and hope for the best.</li>
<li>Peer to peer: There’s no client and no server. Everything is
just a computer.</li>
<li>Unencrypted and untrusted: No one has to obey each other's wishes,
and everyone can do wild shit on every step of the process. As
you'll see soon, this is not a bug but a feature.</li>
</ul>
<p>These principles always stay true, and when they don't, it's purely by
convention. Computers can agree to follow conventions, but it's not
mandatory.</p>
<p>Now here is where your teacher would show you a chart of the &quot;OSI
model&quot; to explain what different protocols on different layers do. The
chart in question looks something like this:</p>
<ul>
<li>Layer 1: Physical</li>
<li>Layer 2: Link</li>
<li>Layer 3: Network</li>
<li>Layer 4: Transport</li>
<li>Layer 5: Session</li>
<li>Layer 6: Presentation</li>
<li>Layer 7: Application</li>
</ul>
<p>That's nice and all, but there's one detail missing here: This model
wasn't decided for TCP/IP. It was designed, as the name suggests, for
the <a href="https://en.wikipedia.org/wiki/OSI_protocols">OSI protocols</a> which is a completely unrelated suite that
competed with TCP/IP in the '80s but which no one uses today. It
simply happens that this abstract model sort of works for describing
any network, including TCP/IP if you pretend Layers 5 to 7 don't exist
(most of the time, they're covered by a single protocol — HTTP) and
Layer 3 includes IP and nothing else.</p>
<p>For the sake of simplicity, I'm going to pick 1 most common protocol
from each layer, one that you're likely using at home, and describe
how things would work for an average person. There are, of course,
more protocols but they mostly follow the same principles.</p>











<hgroup>
    <h2 id="layer-1-cat-5e-cable">
        Layer 1: Cat 5e cable
    </h2>

    <a href="#layer-1-cat-5e-cable" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Layer 1: Cat 5e cable'</span>
    </a>
</hgroup>



<p>Before we can create a network by wiring several computers together,
we should wire at least two. In order to get connected, computers have
a piece of hardware called a <strong>network interface</strong>, also known as a
network card or a network adapter. All the network interface does is
send and receive bits over some medium. That medium is usually a cable
for wired transmission or air for wireless transmission. When 2
computers are physically in contact with each other via either of
them, this connection is called a <strong>network segment</strong>.</p>
<p>The type of cable we're interested in is called <strong>Category 5e</strong>,
usually shortened to Cat 5e. Since virtually every Ethernet network
that people usually encounter uses it, it's sometimes also called an
&quot;Ethernet cable&quot;. The cable itself is 8 copper wires, all wrapped in
plastic and connected to a head that can be easily inserted into an
interface. When you send data, the interface uses a technique called
<strong>amplitude modulation</strong> which is basically picking 2 voltages and
saying that one of them is 1 and the other is 0.</p>
<p>So now we have 2 computers wired together. They can send and receive
data, but as you can tell, this won't quite scale well. If we want to
have more than 1 segment, we need to agree on what to send over that
cable.</p>











<hgroup>
    <h2 id="layer-2-ethernet">
        Layer 2: Ethernet
    </h2>

    <a href="#layer-2-ethernet" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Layer 2: Ethernet'</span>
    </a>
</hgroup>



<p>The most straightforward way to connect a lot of computers together is
by using a device called a <strong>switch</strong>, which is called this way
because it does <strong>packet switching</strong> — going through every packet of
data it receives, one at a time, and resending it wherever it belongs.
The device itself isn't anything out of ordinary — it's a computer,
usually underpowered, with a fuckton of network interfaces which is
all you need for this job. Your &quot;home router&quot; is really a switch and a
router wearing a trenchcoat.</p>
<p>Also the switch is not the only thing you can use here. After all, if
you don't want your device to even think where to send what, you can
use a <strong>hub</strong> which will happily broadcast packets indiscriminately to
everyone connected. You can even go one step back and wire your
computers in a circle or wire every computer to every other computer.
You can then call your masterpiece a <strong>network topology</strong> so you sound
like a true nerd to your friends. Sky is the only limit here!</p>
<p>How does the switch understand which computer is trying to talk to
which? Using a protocol called Ethernet that gives the bits in the
stream of data a meaning. The data is sent in chunks called <strong>frames</strong>
that can have a payload of any size from 46 to 1500 bytes + a bunch of
metadata. There are multiple ways to encode all of this, but the only
one that actually matters is called Ethernet II. Apart from a funny
series of ones and zeroes used to synchronize the transmission, the
metadata has stuff like the checksum (that isn't perfect), which Layer
3 protocol is being sent, and the source and destination MAC
addresses.</p>
<p>As you've probably guessed, the <strong>MAC address</strong> is the bit we're
interested in, as network interfaces use them to identify themselves
to each other. The address itself is usually built into the network
interface and is allocated to its manufacturer by the company called
<a href="https://www.ieee.org/">IEEE</a>, who manages them. There are also 2 special addresses: a
<strong>loopback</strong> (00:00:00:00:00:00) which is like sending a letter to
yourself and a <strong>broadcast</strong> (FF:FF:FF:FF:FF:FF) which is like asking
your switch to become a hub for a moment.</p>
<p>At this point, you may already see a potential issue with this: If
computers self-identify themselves, what's stopping them from claiming
to be someone else? The answer is absolutely nothing! In fact,
<a href="https://source.android.com/docs/core/connect/wifi-mac-randomization-behavior">Android</a> and <a href="https://support.apple.com/guide/security/wi-fi-privacy-secb9cb3140c/web">iOS</a> devices do exactly that when discovering Wi-Fi
networks. (Wi-Fi is unrelated to Ethernet but both use MAC addresses.)
Additionally, this adds a bonus that there could be several computers,
called <strong>nodes</strong> in this context, behind a segment, which allows
tricks like wiring 2 switches together and making it just work™ with
no effort.</p>
<p>But wait, how does a switch figure out which port corresponds to which
node? Why, of course, by analyzing the traffic! Since every frame
contains its source address, the switch can look at which addresses
come from which port and dynamically build a <strong>switching table</strong>. If
the table doesn't have the needed address yet, no problem — it'll
broadcast the frame instead. Or I suppose you could configure the
table manually if your switch is advanced enough.</p>
<p>Now we have several computers, all connected to a switch. One sends a
frame to another, and it's successfully received. What can it do with
that frame? Theoretically, anything, but realistically, if it sees the
destination address is wrong, it'll discard it. But you can't always
be 100% sure — a node could be malicious and listening to everything.</p>











<hgroup>
    <h2 id="layer-3-ip">
        Layer 3: IP
    </h2>

    <a href="#layer-3-ip" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Layer 3: IP'</span>
    </a>
</hgroup>














<hgroup>
    <h3 id="internetworking">
        Internetworking
    </h3>

    <a href="#internetworking" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Internetworking'</span>
    </a>
</hgroup>



<p>For obvious reasons, we can't connect every computer in the world to a
single network. We can, however, connect all of the networks between
each other and create a big network that consists of networks. An
<strong>Internet</strong>, if you will. <strong>IP</strong> is the protocol that makes it
possible by not only specifying which computer to send data to, but
also which network.</p>
<p>The same way switches connect computers, <strong>routers</strong>, also called
gateways in some contexts, connect networks. They usually do it by
being part of several of them at once and relaying the packets they
receive to the right one. But it's important to remember — they don't
really have to do that. Like it happens with governments in real life,
all it means to be a router is that other computers recognize you as
one. Instead of sending packets to the right network, a router can,
for example, purposefully send them to the wrong one, do what you
expect but record the data, send the right payload but change the
metadata, or even do nothing. &quot;Gaslight, gatekeep, girlboss&quot; truly is
the moral imperative here.</p>
<p>And as a fun consequence of that — there may not necessarily be
exactly 1 router on a network. There may be 0, in which case you're
stuck with a single network, or there may be multiple routers, which
is vanishingly unlikely for you to encounter and yet not technically
impossible.</p>











<hgroup>
    <h3 id="ip-addresses">
        IP addresses
    </h3>

    <a href="#ip-addresses" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'IP addresses'</span>
    </a>
</hgroup>



<p>Communication over IP is done by sending <strong>packets</strong>, this time not
called something weird like &quot;frames&quot;, over whatever Layer 2 protocol
is being used, which for us, is Ethernet. Packets can be up to 65535
bytes in size (including all of the metadata), and since that's bigger
than an Ethernet frame, they sometimes have to be either
<strong>fragmented</strong> among several of them (IPv4) or just not be that big
(IPv6). In order for fragmented packets to be properly reassembled,
each one gets a matching <strong>Identification</strong> field.</p>
<p>As you probably know, there are 2 versions of IP: <strong>IPv4</strong>, the older
one that stuck with us for way too long, and <strong>IPv6</strong>, the objectively
better newer one that, at the time of writing, still only has <a href="https://radar.cloudflare.com/adoption-and-usage">38%
adoption</a>. For your convenience, I'll be covering both of them. Their
packets have quite different layouts, but they both encode pretty much
the same stuff like the version of the protocol, how long the headers
and the payload are, a few hints to assist delivery, and a thing
called <strong>time to live</strong> (renamed to hop limit in IPv6). The last one
instructs routers to drop the packet after it's been resent too many
times and accidentally makes traceroute possible. Oh yeah, and also
the source and destination <strong>IP addresses</strong>.</p>
<p>The main difference between the addresses in the 2 versions is their
size. IPv4 addresses are 32 bits and are usually written down as 4
decimal numbers, one for each byte, separated by dots — for example,
192.0.2.23. IPv6 addresses are 128 bits which is 4 times as big, so
they're instead written down as 8 hexadecimal numbers, one for each 2
bytes, separated by colons — for example, 2001:db8:0:0:0:0:0:23. If
you have several zeroes in a row, you can collapse them — the example
above becomes 2001:db8::23. And yes, this doesn't <em>only</em> work in the
middle:</p>
<pre tabindex="0"><code>1:0:0:0:0:0:0:0 = 1::
0:0:0:0:0:0:0:1 = ::1
0:0:0:0:0:0:0:0 = ::
</code></pre><p>In general, there are 2 kinds of addresses: <strong>globally-routable</strong> and
<strong>reserved</strong>. Globally-routable addresses can, as the name suggests,
be routed to from anywhere as long as it's on the Internet, if things
go according to the plan. But again, they don't have to. Reserved
addresses, on the other hand, are used for stuff that isn't on the
Internet, like private networks, documentation (hey, I used a couple
of them above), denoting the same machine (127.0.0.0/8 and ::1),
denoting that we don't know the address (0.0.0.0 and ::), and black
magic like translating IPv6 to IPv4. You can read the <a href="https://datatracker.ietf.org/doc/html/rfc6890">full list of
reserved addresses</a> if you want.</p>
<p>If you've ever noticed how every IPv4 address on a home network starts
with 192.168., reserved addresses are the reason why. What's even
cooler, however, is that every IPv4 address that starts with 10. is
also reserved, which means you can set your home router's address to
10.69.4.20. Now that's what I call a party trick.</p>
<p>In case you're wondering who controls who gets which addresses: <a href="https://www.iana.org/">IANA</a>
does. How is it different from <a href="https://www.icann.org/">ICANN</a>, its parent company? God
fucking knows, but as far as I understand, IANA manages IP addresses
and DNS names that aren't gTLDs (stuff like .com) or ccTLDs (stuff
like .uk) while ICANN manages gTLDs and gives money and people to IANA
so they can do their job. Except IANA doesn't really &quot;control&quot; IP
addresses, it gives them to <a href="https://en.wikipedia.org/wiki/Regional_Internet_registry">regional registries</a>, and actual control
is done via <a href="https://quantum5.ca/2023/07/14/introduction-to-bgp-from-operator-of-small-as/">BGP</a>, but let's not get into that.</p>











<hgroup>
    <h3 id="routing-and-subnetting">
        Routing and subnetting
    </h3>

    <a href="#routing-and-subnetting" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Routing and subnetting'</span>
    </a>
</hgroup>



<p>Alright, say we know which IP address to send data to. There are 2
things we can do (apart from doing nothing): If we know for a fact
that wherever that address points to is physically on the same
network, then we can send the packets there ourselves. After all, if
we know the destination MAC address, we have no use for a router. If
we know for a fact it isn't on the same network, then we send it to a
router. Assuming everything goes right, the router will be able to
send the packets either directly to the destination or another router,
and the process will repeat until the data arrives. If the destination
isn't valid or any router along the way decides not to cooperate, the
data will obviously never arrive.</p>
<p>Keeping in mind that a router is merely a computer with a role: Like
with Ethernet frames, a computer is free to do whatever it wants with
IP packets it receives, but realistically, it'll look at the
destination address and give up trying to process the packet if it
doesn't match any of the addresses it's interested in. That is unless
it decides to <strong>route</strong> that packet somewhere else. Linux calls this
process &quot;IP forwarding&quot; and lets you enable it per network interface.
So if you enable it for, say, <code>enp1s0</code>, all packets received there,
that weren't sent directly to your computer, will be routed.</p>
<p>All you really need to know about routing is that it's basically
resending packets from one network interface to another. Preferably
unchanged, but no one is there to stop the opposite from happening. In
order to figure out where to resend, or well, send stuff at all,
computers use a thing called a <strong>routing table</strong>. The table consists
of entries that say which network corresponds to which interface and
which router to send packets to if the network isn't directly
reachable. The router that's used for packets that don't have anywhere
else to go is called the <strong>default gateway</strong>.</p>
<p>Wait, but what the hell does &quot;network&quot; even mean in this context? It's
a long story: Since having a separate entry for every single address
would be insane, ranges of addresses are used instead. These ranges
are formulated by slicing an address in 2 and calling the 2 resulting
parts the network, also known as the <strong>subnet</strong> if it's inside a
bigger network, and the <strong>host</strong>. The number of bits given to the
network is called a <strong>prefix</strong> and is usually written down separated
from the address with a slash. This way of writing it is called the
<strong>CIDR notation</strong>. For example, 192.0.2.23/24 means that we should
slice the address into a 24 bit network — 192.0.2.x — and an 8 bit
host — x.x.x.23 — and think &quot;huh okay, we're referring to the host 23
inside 192.0.2.0/24&quot;.</p>
<p>What's the difference between 192.0.2.23/24 and 192.0.2.23/23? There
isn't any if neither network is in our routing table. For all we know,
they're the same address. What does an address with an all-zeroes host
like 192.0.2.0/24 mean? It means we're referring to the network as a
whole and not any computer inside it. That's the kind of range I was
talking about. What does an address with an all-ones host like
192.0.2.255/24 mean? It means if you send a packet there, the router
of that network will broadcast it. What does IPv4 mean by a &quot;subnet
mask&quot;? It's a fancy way of writing down the prefix as a binary mask
with N ones in the beginning. So a /24 prefix and a 255.255.255.0 mask
are the same thing. Why was I forced to manually calculate this shit
on paper in college? Because they're sadists.</p>
<p>Got it? Great. So given an address, we look through every entry in the
routing table and try to find matching networks. If the network is
192.0.2.0/24, then the IP matches if its lowest 24 bits match with the
network's. If there are multiple matches, then we find out whether
that damn 192.0.2.23 is 192.0.2.23/24 or 192.0.2.23/23 by picking the
network with the longest prefix and sending packets to the
corresponding interface. Finally.</p>
<p>Or do we? We know the destination address but not the source address.
So uhhhhh…</p>











<hgroup>
    <h3 id="how-do-you-get-the-ip-address-in-the-first-place-">
        How do you get the IP address in the first place?
    </h3>

    <a href="#how-do-you-get-the-ip-address-in-the-first-place-" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'How do you get the IP address in the first place?'</span>
    </a>
</hgroup>



<p>Well, you don’t really get <em>the</em> IP address, you get <em>an</em> IP address.
Not only can a computer have several interfaces connected to different
networks, but it can also have more than a single address on the same
network. Also remember what I said about having multiple routers on
the same network? So yeah, chances are you'll get a couple more of
them than you expect.</p>
<p>Anyway, let's get the most obvious solution out of our way beforehand:
If you know exactly what network your computer always connects to and
how it behaves, you can set your <strong>static</strong> address and default
gateway manually. There's nothing stopping you from doing that, and if
your computer is a server that lives in the same datacenter for years
at a time, this is your most rational choice. Whether your router is
going to like that is a different matter.</p>
<p>If your computer is a phone, however, or you can't ever be bothered
configuring anything, then it'd be really nice if it could negotiate a
<strong>dynamic</strong> address for itself. Luckily, that's exactly what <strong>DHCP</strong>
does, and it does that for both IPv4 and IPv6. That is unless you use
Android because Google decided you don't need it for IPv6. Read this
<a href="https://issuetracker.google.com/issues/36949085">11 year old bug report</a> they closed as &quot;won't fix&quot; for more info.</p>
<p>The way DHCP functions is quite simple: There's a client — your
computer that wants an address — and a server — usually a program
running on your router, but it can be on a separate machine. The
client sends a <strong>discover</strong> message to the server via UDP (more on
that later) with stuff like &quot;hey, this is my MAC address and I'd
really like to have an IP address, preferably that one&quot;, and after a
bunch of back and forth <strong>offers</strong> from the server and <strong>requests</strong>
from the client, they hopefully arrive at an <strong>acknowledgement</strong>. The
client receives the information it needs to send stuff: its own
address, how long it can have that address for, the address of the
gateway, the prefix/subnet mask so it can populate the routing table
with its own network, the address of the DNS server, and possibly
other things.</p>
<p>But hold on. The client sends how and where? It knows neither the
address of the server nor its own address. Does it send messages to a
fixed location? No, it instead screams to everyone on the network with
a broadcast frame and hopes someone replies. What does it use as the
source/destination addresses? 0.0.0.0 and 255.255.255.255, which is
like saying &quot;I don't know&quot; and &quot;anyone who can hear me&quot;. The IPv6
version of the protocol does it slightly differently by using a
<strong>multicast</strong> address which is practically the same thing, except the
client is only screaming to the computers that are explicitly
listening for DHCP messages. Also yes, your intuition is completely
right here. A malicious third party can absolutely spoof this.</p>
<p>And this is all fine and dandy, but DHCP still has a fundamental flaw
despite being this simple — it requires a centralized server. Doesn't
sound quite &quot;plug and play&quot;, does it? Understandably, IPv6 has a
solution for that, called <strong>SLAAC</strong>. That's one hell of a funny name.
The way this protocol works is somehow even more straightforward, if
you can believe that. In fact, it's so straightforward that IPv4 had
its own version of it called IRDP that unfortunately went nowhere. Oh
well.</p>
<p>When using SLAAC, your computer starts with outright making up a
<strong>link-local</strong> address for itself by taking a fe80::/64 network prefix
and <a href="https://datatracker.ietf.org/doc/html/rfc7217">shoving some random bytes</a> into it. The address is already being
used by someone else? Eh, just make up a new one. &quot;Link-local&quot;, by the
way, means that it's a reserved address that can only be used on the
current network and which is always present, even if you're completely
isolated from the Internet. If you've ever noticed that your computer
has an IPv6 address but no IPv6 Internet connectivity, this is why.</p>
<p>After getting a link-local address, your computer, similarly to what
it does with DHCP, uses multicast to discover routers, but this time
using ICMP <strong>Router Solicitation</strong> (more on that also later) instead
of UDP. In response, the routers on the network, if they feel like it,
respond with a <strong>Router Advertisement</strong>. If the response isn't &quot;fuck
off and use DHCP&quot;, your computer picks up their addresses, DNS server
configuration, and globally-routable prefixes they send back. Now we
have everything we need for real.</p>
<p>As you can see, this time, we got a whole prefix instead of one
specific globally-routable address. Does this mean your computer can
shove some random bytes into it too? Yes, that's exactly what it
means! Or well, it can also shove <a href="https://datatracker.ietf.org/doc/html/rfc4291#page-20">its MAC address</a>, but that's a poor
practice since then the Internet servers you connect to will be able
to see your MAC address. Fortunately, modern operating systems,
including Linux if you use <a href="https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/nm-1-12/NEWS#L367-369">NetworkManager</a>, don't do that anymore. If
you're unsure about yours, look for &quot;IPv6 interface identifier
generation&quot; or something like that in your network daemon's settings.</p>
<p>There's only one piece of the puzzle left: How do you find if an IP
address is used by someone on the network? Or for that matter, how do
you find the MAC address of the router from its IP address? The answer
for both questions is <strong>ARP</strong> for IPv4 and <strong>NDP</strong> for IPv6, both of
which are stupidly simple protocols.</p>
<p>Their entire principle of operation is broadcasting &quot;anyone know this
IP address?&quot; and seeing if anyone sends &quot;yeah, here's the MAC address&quot;
back. The only major difference between the two is that ARP is sent
directly over, in our case, Ethernet, effectively displacing an IP
packet, while NDP is sent via ICMP. And yes, once again, both can be
and <a href="https://en.wikipedia.org/wiki/ARP_spoofing">are spoofed</a> by hackers.</p>











<hgroup>
    <h2 id="layer-4-udp-and-icmp-">
        Layer 4: UDP and... ICMP?
    </h2>

    <a href="#layer-4-udp-and-icmp-" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Layer 4: UDP and... ICMP?'</span>
    </a>
</hgroup>



<p>Let's address the elephant in the room: ICMP is not a Layer 4
protocol, even though it's sent on top of an IP packet as payload.
Actually, the same applies to ARP — it's not Layer 3, even though it's
sent on top Ethernet. Yes, this makes no fucking sense and is clear
evidence that computer people should never be allowed to categorize
stuff, but it is technically consistent with the OSI model: ICMP
doesn't transport and ARP doesn't network. This fact, however, is
completely irrelevant because real protocols don't care. This is the
exact kind of OSI and TCP/IP mismatch I was talking about. To make our
lives easier, let's pretend it's Layer 4.</p>
<p><strong>ICMP</strong>, to put it short, is an error reporting mechanism for IP.
Pretty much all it does is send a code to identify what happened to a
packet and maybe some additional data. How does it identify the
packet? By sending the first bytes of it as the payload, duh! What can
it say about the packet? A lot of things, including &quot;I don't want to
accept your packets&quot;, &quot;your packet was way too big&quot;, and &quot;you didn't
send any packet, but thanks for making sure I'm still alive; here's
your data back&quot;. The last one is known as <strong>Echo</strong> or, more commonly,
ping. Plus, as I mentioned before, NDP uses it for MAC address and
router discovery while traceroute uses it to trace which addresses a
packet travels through.</p>
<p>If you want to send proper data, you aren't going to use ICMP unless
you're <a href="https://www.youtube.com/watch?v=JcJSW7Rprio">this guy</a>. You're going to use <strong>TCP</strong> or <strong>UDP</strong>. I'll only
be covering UDP since it's more relevant to the whole routing aspect
of TCP/IP, and its basic principles also apply to TCP. But the gist
is: TCP is not connectionless, i.e. the client and the server have to
shake their hands before sending stuff, and it tries really hard not
to lose or reorder anything along the way. UDP doesn't do that. Why
would you use it then? It's a lot faster, which is good for stuff like
video games.</p>
<p>Compared to a plain IP packet, UDP provides 2 additional features:
Rudimentary error checking (a checksum) and multiplexing, i.e. letting
you send multiple streams of data over one address. As you can
probably tell, packets being identified by their address alone doesn't
let you do that. UDP does this by providing 2 additional 16 bit
<strong>port</strong> numbers with every packet, one for the source address and one
for the destination address.</p>
<p>What you need to keep in mind here is that every port is <strong>duplex</strong>
which is a smart way of saying &quot;sends data both ways&quot;, so you only
need one for two-way communication. In other words, there aren't
really &quot;source ports&quot; and &quot;destination ports&quot;, strictly speaking. Your
computer has 65536 ports total, so whatever port it picks as the
source will also be used as the destination by whoever replies. For
this reason, if it needs to send something as a client, it'll use a
random, <strong>ephemeral</strong> port.</p>
<p>However, you're running server, it's certainly a good idea for it to
accept requests on a stable, <strong>well-known</strong> port. Usually, those ports
have a number below 1024 and require root to bind to, but not always.
A few examples of such ports are 80 for HTTP, 443 for HTTPS, 53 for
DNS, 123 for NTP, and 25565 for Minecraft: Java Edition, the most
important piece of networking software. If you want to look through
all the standard ports, IANA has got a <a href="https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml">nice big list</a> for you.</p>
<p>Wait, <strong>bind</strong>? Yup, it means assign a program on your computer to a
port and an address, so it and only it is able to send and receive
stuff over it. A security mechanism of sorts. When you send an HTTP
request, you bind to a port, preferably an ephemeral one, and when you
<strong>listen</strong> to these requests, you also bind to a port, preferably 443
because not using TLS in the year of our Lord 2024 is a crime.</p>











<hgroup>
    <h2 id="layer-3-one-more-time-nat">
        Layer 3, one more time: NAT
    </h2>

    <a href="#layer-3-one-more-time-nat" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Layer 3, one more time: NAT'</span>
    </a>
</hgroup>



<p>As you surely know, there are 8 billion people on the planet and only
4.2 billion IPv4 addresses, which is really bad. Well, guess what,
you're wrong! There aren't 4.2 billion <em>globally-routable</em> addresses.
Remember — reserved addresses exist. If we exclude those, including a
mysterious 268 million address hole in 240.0.0.0/4 that was reserved
for &quot;future use&quot; but never actually used, we only get 3.9 billion
addresses. On top of that, most of them are allocated to multinational
corporations with big datacenters and big bucks, not residential
areas. Now <em>that's</em> bad.</p>
<p>Obviously, you're reading this article on the Internet right now and
you're likely using IPv4. Okay, maybe you printed it, but someone had
to get it from the Internet before that. And that someone didn't have
to wait in a queue for a week to get a turn at using their IP address
(hopefully). How come? The answer is a good dose of unholy rituals
that your ISP performs, also known as CGNAT or, more generally,
<strong>NAT</strong>.</p>
<p>Here's a few fun observations: You probably aren't hosting your own
Internet services at home. Almost everything that you send is either
TCP or UDP. You probably aren't using all 65536 ports of either
protocol at once. See where I'm going with this? What if I give you
and your friends reserved addresses, then track the port numbers
you're using, send your stuff as my own using my single
globally-routable address with different ports, and then give you the
stuff that comes back as if it'd been sent to you. Trust me, bro, you
won't notice it™.</p>
<p>Yes, this is pretty much what NAT subjects you to. Lies and deception.
You think you have an entire address for yourself, but all you get is
a port per connection, which NAT is desperately waiting for you to
forget about for a few minutes so it can give it to someone else. You
think you can let people send packets to you, but NAT's grim ghostly
hand points to a sign that reads &quot;your packet shall go out first&quot; and
doesn't even give you a port. Your existence is reduced to nothing but
being a pawn in NAT's master plan to conquer the world.</p>
<p>Oh yeah, also it spoofs the Identification field. These aren't aware
of ports, after all.</p>








    
        

        

        

        




<hgroup>
    <h2 id="conclusion-2">
        Conclusion
    </h2>

    <a href="#conclusion-2" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Conclusion'</span>
    </a>
</hgroup>



<p>Be a good boy/girl/bunny and use IPv6. Please :)</p>

                ]]></content></entry><entry><title>Coping with intrusive thoughts</title><summary>Things that helped me personally.</summary><updated>2024-01-02T00:00:00Z</updated><id>https://www.bruh.ltd/blog/coping-with-intrusive-thoughts/</id><link rel="alternate" href="https://www.bruh.ltd/blog/coping-with-intrusive-thoughts/"/><content type="html"><![CDATA[
                    <p>This is not really a guide or a story but a short list of information
that personally helped me cope with my intrusive thoughts, which I
wish I was told about earlier.</p>
<ul>
<li>Your brain amplifies worries and uncertainty.</li>
<li>Your thoughts are separate from who you are.</li>
<li>There's no need to blame yourself for your thoughts.</li>
<li>Your actions matter more than your thoughts.</li>
<li>Sometimes doing nothing is better than desperately trying to find
what to do.</li>
<li>Accept your thoughts as background noise that doesn't need to be
interacted with.</li>
<li>Mocking, rebutting, agreeing with, or trying to stop your thoughts
will only make them worse.</li>
<li>Don't make a big deal out of it — it's okay if you slip up.</li>
<li>Change the atmosphere in a healthy way (touch grass).</li>
</ul>

                ]]></content></entry><entry><title>Every flavor of Choco Pie, ranked</title><summary>Yes, my stomach hates me.</summary><updated>2023-10-11T00:00:00Z</updated><id>https://www.bruh.ltd/blog/every-flavor-of-choco-pie-ranked/</id><link rel="alternate" href="https://www.bruh.ltd/blog/every-flavor-of-choco-pie-ranked/"/><content type="html"><![CDATA[
                    <p>First of all, let's start with some definitions:</p>
<ul>
<li>By &quot;Choco Pie&quot; I mean the brands of candy called &quot;Choco Pie&quot; by
Orion and Lotte. The candy with the same name from other companies,
like Tondi, are specifically excluded because they're all garbage.</li>
<li>By &quot;every flavor&quot; I mean every flavor that was sold in retail in
Russia at the time of writing. There are more flavors, but they're
only sold in other countries like India, and I don't live there.</li>
</ul>











<hgroup>
    <h2 id="differences-between-the-two-brands">
        Differences between the two brands
    </h2>

    <a href="#differences-between-the-two-brands" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Differences between the two brands'</span>
    </a>
</hgroup>



<p>In order to not repeat the same stuff more than necessary, here are
the things that are common to all flavors of the given brand. Keep
them in mind when trying to picture what a flavor would taste like to
you:</p>
<ul>
<li>Orion flavors are generally softer and rounder. This, however,
doesn't mean that they fall apart easier.</li>
<li>Lotte flavors are generally more sweet but not terribly so.</li>
<li>Orion flavors generally have more, well, flavor. For example, you
can actually taste the vanilla in the vanilla flavor.</li>
<li>Lotte flavors are usually cheaper and easier to find, especially in
smaller quantities. In contrast to Orion flavors, with the notable
exception being Original, which are almost exclusively sold in
12-packs, Lotte flavors are trivial to find in 6-packs.</li>
<li>Orion has more flavors. Many more flavors.</li>
<li>They're both a waste of your money if you can eat something better.
Don't repeat my mistake of eating all 12 of them from a 12-pack on a
semi-regular basis. This is neither healthy nor wise financially.</li>
</ul>











<hgroup>
    <h2 id="the-ranking™">
        The Ranking™
    </h2>

    <a href="#the-ranking%e2%84%a2" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'The Ranking™'</span>
    </a>
</hgroup>



<p>From best to worst, split into categories.</p>











<hgroup>
    <h3 id="awesome-fruit-flavors">
        Awesome fruit flavors
    </h3>

    <a href="#awesome-fruit-flavors" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Awesome fruit flavors'</span>
    </a>
</hgroup>



<ol>
<li>Black Currant, Orion</li>
<li>Cranberry, Orion</li>
</ol>
<p>A vanilla purist may condemn my decision to rank these two the
highest, but I genuinely think they deserve it. They both have lots of
jam inside, taste like the actual fruit they're supposed to represent,
and are just right amount of sweet. I also love black currant as a
berry (it's probably second to my favorite), so I'm bit biased here
anyway.</p>











<hgroup>
    <h3 id="baseline">
        Baseline
    </h3>

    <a href="#baseline" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Baseline'</span>
    </a>
</hgroup>



<ol start="3">
<li>Original, Orion</li>
</ol>
<p>If you're picking a Choco Pie for the first time, this is likely your
safest bet, which you could probably already tell by the number of
flavors ranked lower. Also let's be real, it should've been called
&quot;Vanilla&quot;. &quot;Original&quot; is way too fancy of a name.</p>











<hgroup>
    <h3 id="good-fruit-flavors">
        Good fruit flavors
    </h3>

    <a href="#good-fruit-flavors" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Good fruit flavors'</span>
    </a>
</hgroup>



<ol start="4">
<li>Vienna Cake, Orion</li>
<li>Cherry, Orion</li>
<li>Raspberry, Orion</li>
</ol>
<p>These are about as well produced as the fruit flavors ranked higher,
but in my opinion, don't taste as good. Vienna Cake (what even <em>is</em>
this name) hits the right spot even though it uses Dark as its base
which I'm not that big of a fan of. The peach jam tastes more like
orange jam, but I still have to say the combination of the two works
really well. Raspberry, on the other hand, is my favorite berry, but
for some reason, I'm not a fan of raspberry jam. The Choco Pie
unfortunately doesn't manage to make me a fan of it. It's still good
but I'd very much rather eat strawberry jam.</p>








    
        

        

        

        




<hgroup>
    <h3 id="baseline-2">
        Baseline
    </h3>

    <a href="#baseline-2" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Baseline'</span>
    </a>
</hgroup>



<ol start="7">
<li>Vanilla, Lotte</li>
</ol>
<p>If your only choices are this and a fruit flavor you haven't tried
yet, this is likely your safest bet. It's not quite as good, in my
opinion, as Original but it's not much worse. By the way, it's not
really called &quot;Vanilla&quot; since the box doesn't name any flavor.</p>











<hgroup>
    <h3 id="acceptable-fruit-flavors">
        Acceptable fruit flavors
    </h3>

    <a href="#acceptable-fruit-flavors" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Acceptable fruit flavors'</span>
    </a>
</hgroup>



<ol start="8">
<li>Apple-Cinnamon, Orion</li>
<li>Chocochip &amp; Orange, Orion</li>
<li>Mango, Orion</li>
<li>Dark, Orion</li>
<li>Caramel, Orion</li>
<li>Poppy, Orion</li>
</ol>
<p>These are generally not that great in my opinion. Well, except for
Caramel which is simply indistinguishable from Dark. Maybe I got
unlucky and mine happened to have little to no caramel in it. Dark
itself, by the way, is uhh... Well, don't get me wrong, it's fine and
has its unique flavor, but I would very much rather eat an Original. I
just don't vibe with it. In fact, I don't vibe with it exactly the
same way I don't vibe with the poppy seeds in Poppy. In this case,
however, the additional flavor is more weird and less interesting.</p>
<p>Either way, the other 3 flavors are not that noteworthy.
Apple-Cinnamon tastes like an actual apple and I can sorta get behind
it. I'm not sure if I can taste the cinnamon, but to be fair, I
haven't ever tried actual cinnamon. The chocolate chips in the
Chocochip &amp; Orange are a bit gimmicky but don't hurt. Mango is decent
but that's about it. But hey, at least it's already miles ahead of the
mango flavor of Bounty.</p>











<hgroup>
    <h3 id="bad-fruit-flavors">
        Bad fruit flavors
    </h3>

    <a href="#bad-fruit-flavors" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Bad fruit flavors'</span>
    </a>
</hgroup>



<ol start="14">
<li>Strawberry, Orion</li>
<li>Strawberry, Lotte</li>
<li>Banana, Lotte</li>
</ol>
<p>These are not worth your money. They don't have any actual jam inside
but instead have a bit of food coloring and a flavoring agent that
tastes vaguely like fruit. And yes, this includes Strawberry by Orion,
which is incredibly underwhelming. It's supposed to have strawberry
jam, but I swear couldn't taste any. I would've loved it otherwise.</p>











<hgroup>
    <h3 id="garbage">
        Garbage
    </h3>

    <a href="#garbage" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Garbage'</span>
    </a>
</hgroup>



<ol start="17">
<li>Cacao, Lotte</li>
<li>Coconut, Orion</li>
</ol>
<p>Do not buy these flavors. Cacao is a disgusting bitter piece of shit
that's nowhere near being comparable to Dark. This is strange,
considering Lotte flavors are generally more sweet which should help,
but it fucking doesn't. Coconut is Original that tastes like it had
cum diluted in its marshmallow. It may not sound that bad (okay, maybe
it does) but remember: this is considered a &quot;premium&quot; flavor, making
it a third more expensive. I regret paying for it. No wonder no one
else wants to buy them.</p>











<hgroup>
    <h2 id="conclusion">
        Conclusion
    </h2>

    <a href="#conclusion" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Conclusion'</span>
    </a>
</hgroup>



<p>Just buy vanilla.</p>

                ]]></content></entry><entry><title>How to test your RISC-V emulator</title><summary>It's a bit tricky but worth the effort.</summary><updated>2023-08-08T00:00:00Z</updated><id>https://www.bruh.ltd/blog/how-to-test-your-risc-v-emulator/</id><link rel="alternate" href="https://www.bruh.ltd/blog/how-to-test-your-risc-v-emulator/"/><content type="html"><![CDATA[
                    <p>Recently, I had a chance to learn about RISC-V emulation because I
needed a CPU for <a href="https://gitlab.com/cczp/act-3/bm1">my fantasy computer</a>. Writing an emulator was,
surprisingly, not a frustrating experience because of not only the
<a href="https://riscv.org/technical/specifications/">ISA specification</a> being open source and written in an understandable
language, but also a great official <a href="https://github.com/riscv-software-src/riscv-tests">test suite</a>. Unfortunately, the
suite's documentation isn't that comprehensive and is only rarely
mentioned online. As such, here's a small guide on how to use it.</p>
<p>But first, a little disclaimer: As you can probably tell, I'm not a
low-level development guru. There's probably a better way to do it, so
take everything with a grain of salt.</p>











<hgroup>
    <h2 id="toolchain">
        Toolchain
    </h2>

    <a href="#toolchain" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Toolchain'</span>
    </a>
</hgroup>



<p>In order to build the test cases (or well, any native RISC-V
software), you need a toolchain. The 2 most popular options you have
are GCC and LLVM, and I recommend using the former since that's what
the test suite was written in mind. LLVM is likely possible to use
with a minor makefile modification, but I didn't bother.</p>
<p>The easiest way to get the whole GCC toolchain is to either get it
from your Linux distro (if it offers a <code>riscv64-unknown-elf</code> one) or
build it manually using the <a href="https://github.com/riscv-collab/riscv-gnu-toolchain">official repo</a>. For obvious reasons, I'm
going to cover the second scenario.</p>
<p>Install the build dependencies for your specific distro using the
command in the readme and clone the git repo. You don't really need
<code>--recursive</code> here since there are more submodule dependencies than
most targets need, and it's going to fetch everything at the build
time anyway:</p>
<pre tabindex="0"><code>git clone https://github.com/riscv-collab/riscv-gnu-toolchain.git
</code></pre><p>Next, you need to build the Newlib flavor. I personally prefer using
<code>~/.local</code> as the prefix, so the whole thing is installed for my user
only and requires no black magic other than putting <code>~/.local/bin</code> in
my <code>$PATH</code>:</p>
<pre tabindex="0"><code>./configure --prefix=$HOME/.local
make
</code></pre><p>Depending on how slow your hardware is, the whole process will take an
hour or two. In the meanwhile, you can ensure that you're properly
hydrated, your dishes are washed, and your laundry has been done.</p>











<hgroup>
    <h2 id="test-suite">
        Test suite
    </h2>

    <a href="#test-suite" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Test suite'</span>
    </a>
</hgroup>



<p>First of all, you need to clone the thing. Note that <code>--recursive</code> is
needed here since the repo has a submodule that it doesn't fetch by
itself:</p>
<pre tabindex="0"><code>git clone --recursive https://github.com/riscv-software-src/riscv-tests.git
</code></pre><p>In contrast to what I do with the toolchain, I prefer using a prefix
pointing to a folder near the test suite itself. Since it doesn't
install any executables native to your host, this shouldn't be an
issue. Let's say you have the following file hierarchy in your
project:</p>
<ul>
<li><code>output</code></li>
<li><code>riscv-tests</code></li>
</ul>
<p>In order to build the tests and install them into <code>output</code>, you need
to run the following:</p>
<pre tabindex="0"><code>cd riscv-tests

autoconf
./configure --prefix=&#34;$(realpath &#39;../output&#39;)&#34;

make
make install
</code></pre>










<hgroup>
    <h2 id="okay-now-what-">
        Okay, now what?
    </h2>

    <a href="#okay-now-what-" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Okay, now what?'</span>
    </a>
</hgroup>



<p>As you can probably see, you now have a bunch of tests cases themselves:</p>
<ul>
<li><code>output/share/riscv-tests/isa/</code>
<ul>
<li><code>Makefile</code></li>
<li><code>rv32mi-p-breakpoint</code></li>
<li><code>rv32mi-p-breakpoint.dump</code></li>
<li><code>rv32mi-p-csr</code></li>
<li><code>rv32mi-p-csr.dump</code></li>
</ul>
</li>
</ul>
<p>The object of your interest here is the files with no extension (not
counting <code>Makefile</code>, obviously). They're the native RISC-V binaries in
the ELF format. <code>.dump</code> files are their disassembled versions,
generated with <code>objdump</code>, that are actually quite handy because they
let you quickly debug why a test case fails without having with
manually <code>objdump</code> everything or rolling out your own full-fledged
debugger.</p>
<p>Before even touching any of them, you should consider: does your
emulator frontend support ELF? If not, you should first dump the
contents of the test cases into a flat binary file:</p>
<pre tabindex="0"><code>riscv64-unknown-elf-objcopy -O binary test-case test-case.bin
</code></pre><p>Next, you need to pick the test cases that are actually relevant for
your specific emulator (or &quot;TVM&quot; as the test suite calls them) by
looking at their filenames. For example, here's what different parts
of <code>rv32mi-p-breakpoint</code> mean:</p>
<dl>
<dt><code>32</code></dt>
<dd>XLEN bits. Self-explanatory — pick 32 or 64 depending on which one
you're emulating. There's no need to use both.</dd>
<dt><code>m</code></dt>
<dd>Privilege mode. Depends on which ones your emulator is capable to
operate in, except for <code>u</code> that you're going to need anyway because
it tests the instructions common to all privilege modes. So for
example, if you're implementing the:
<ul>
<li>Unprivileged spec only — use <code>u</code>.</li>
<li>Unprivileged spec + privileged spec (machine mode only) — use <code>u</code>
and <code>m</code>.</li>
<li>Unprivileged spec + privileged spec (machine mode and supervisor
mode) — use <code>u</code>, <code>m</code>, and <code>s</code>.</li>
</ul>
</dd>
<dt><code>i</code></dt>
<dd>Extension/base instruction set. Depends on which ones you care
about. So for example, if you're making an RV64IMAC emulator, you
need to pick <code>i</code>, <code>m</code>, <code>a</code>, and <code>c</code>.</dd>
<dt><code>p</code></dt>
<dd>Target environment. A bit weird to define, so just consult the table
in the test suite's readme. But in short, if you're making a simple
single-hart emulator with no virtual memory support, you need <code>p</code>.</dd>
<dt><code>breakpoint</code></dt>
<dd>Tested instructions. Easy to choose — just pick all of them. Or
well, I guess you can omit <code>ma_data</code> if you don't implement
misaligned loads/stores.</dd>
</dl>











<hgroup>
    <h2 id="running-the-tests">
        Running the tests
    </h2>

    <a href="#running-the-tests" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Running the tests'</span>
    </a>
</hgroup>



<p>For this I'm going to recommend you the approach used by Max Nurzia's
<a href="https://github.com/mnurzia/rv">rv</a> — make a tiny wrapper around your emulator's core and shove the
unmodified test cases into it.</p>
<p>As test cases are just executables that do stuff and make an <code>ecall</code>
when they're done, all you need to do is load them into memory, jump
to the first instruction, and run until you encounter an <code>ecall</code>. In
order to verify if the test passed, you need to look at the
<code>RVTEST_PASS</code>/<code>RVTEST_FAIL</code> macros inside the <code>riscv_test.h</code> header
file of your target environment. For example, here's what they look
like for <code>p</code>:</p>
<pre tabindex="0"><code>TESTNUM: gp

RVTEST_PASS:
    fence
    li TESTNUM, 1
    li a7, 93
    li a0, 0
    ecall

RVTEST_FAIL:
    fence
1:  beqz TESTNUM, 1b
    sll TESTNUM, TESTNUM, 1
    or TESTNUM, TESTNUM, 1
    li a7, 93
    addi a0, TESTNUM, 0
    ecall
</code></pre><p>Which basically means that if a test passed, <code>gp</code> (aka <code>x3</code>) should be
<code>1</code> and <code>a0</code> (aka x10) should be <code>0</code>, and if they aren't, the test
failed.</p>
<p>The easiest way to provide feedback for test coverage is to repeat
this process for each test case, one at a time, and either print the
result or return it as an exit code and let a separate script do the
printing for you. Here's a simplified version of the script I used in
my emulator:</p>
<pre tabindex="0"><code>#!/bin/sh

set -ue

RUNNER=your-wrapper

RED=&#39;\033[0;31m&#39;
GREEN=&#39;\033[0;32m&#39;
NORMAL=&#39;\033[0m&#39;

for CASE in relevant/cases/*
do
    if &#34;${RUNNER}&#34; &#34;${CASE}&#34;
    then
        echo -e &#34;${GREEN}$(basename &#34;${CASE}&#34;): PASS${NORMAL}&#34;
    else
        echo -e &#34;${RED}$(basename &#34;${CASE}&#34;): FAIL${NORMAL}&#34;
    fi
done
</code></pre>
                ]]></content></entry><entry><title>List of common built-in app types</title><summary>Yes, this is exactly what it sounds like.</summary><updated>2023-06-13T00:00:00Z</updated><id>https://www.bruh.ltd/blog/list-of-common-built-in-app-types/</id><link rel="alternate" href="https://www.bruh.ltd/blog/list-of-common-built-in-app-types/"/><content type="html"><![CDATA[
                    <p>The following is a semi-comprehensive and heavily opinionated list of
types of generic applications you'd expect to see preinstalled on a
modern consumer device. There's no exact reason why I created this
other than the fact that I couldn't find anything like this online. I
guess you can use this if you're making a toy OS and you're lacking
ideas.</p>











<hgroup>
    <h2 id="productivity">
        Productivity
    </h2>

    <a href="#productivity" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Productivity'</span>
    </a>
</hgroup>



<ul>
<li>Calculator</li>
<li>Calendar/daily planner</li>
<li>Clock/timer/alarm</li>
<li>Contact browser</li>
<li>Dictionary browser</li>
<li>Map/navigation utility</li>
<li>Notes editor</li>
<li>Presentation utility</li>
<li>Spreadsheet utility</li>
<li>Todo/checklist editor</li>
<li>Translation utility</li>
<li>Weather forecast utility</li>
<li>Word processor</li>
</ul>











<hgroup>
    <h2 id="data-manipulation">
        Data manipulation
    </h2>

    <a href="#data-manipulation" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Data manipulation'</span>
    </a>
</hgroup>



<ul>
<li>Audio editor</li>
<li>Audio player</li>
<li>Bitmap image editor</li>
<li>Font editor</li>
<li>Font viewer</li>
<li>Hex editor</li>
<li>Image viewer</li>
<li>PDF/E-book viewer</li>
<li>Text editor</li>
<li>Unicode character browser</li>
<li>Vector image editor</li>
<li>Video editor</li>
<li>Video player</li>
</ul>











<hgroup>
    <h2 id="networking">
        Networking
    </h2>

    <a href="#networking" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Networking'</span>
    </a>
</hgroup>



<ul>
<li>BitTorrent client</li>
<li>Email client</li>
<li>Fax utility</li>
<li>Password manager</li>
<li>Phone dialer</li>
<li>SMS messenger</li>
<li>Two factor authentication utility</li>
<li>Web browser</li>
</ul>











<hgroup>
    <h2 id="peripheral-hardware-access">
        Peripheral hardware access
    </h2>

    <a href="#peripheral-hardware-access" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Peripheral hardware access'</span>
    </a>
</hgroup>



<ul>
<li>Audio recorder</li>
<li>Camera capture utility</li>
<li>Paper scanner utility</li>
<li>Printer utility</li>
<li>QR code/barcode scanner</li>
<li>Step counter/fitness assistant</li>
</ul>











<hgroup>
    <h2 id="system-maintenance">
        System maintenance
    </h2>

    <a href="#system-maintenance" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'System maintenance'</span>
    </a>
</hgroup>



<ul>
<li>Antivirus utility</li>
<li>Application log viewer</li>
<li>Backup utility</li>
<li>Bulk rename utility</li>
<li>Checksum utility</li>
<li>Data recovery utility</li>
<li>Disk cleanup utility</li>
<li>Disk image browser</li>
<li>Disk image writer</li>
<li>Disk partitioning utility</li>
<li>Disk usage analyzer</li>
<li>File archiver</li>
<li>File browser</li>
<li>File transfer utility</li>
<li>File/disk encryption utility</li>
<li>Hardware information utility</li>
<li>Hardware resource monitor</li>
<li>Help browser</li>
<li>Network analyzer</li>
<li>Process browser</li>
<li>Process scheduler</li>
<li>Remote desktop client</li>
<li>Screen capture utility</li>
<li>Software repository browser</li>
<li>System configuration utility</li>
<li>Terminal emulator</li>
<li>Virtualization/emulation utility</li>
</ul>

                ]]></content></entry><entry><title>The Rule of Two: my housekeeping principle</title><summary>Life advice from a person with barely any experience.</summary><updated>2023-01-30T00:00:00Z</updated><id>https://www.bruh.ltd/blog/the-rule-of-two-my-housekeeping-principle/</id><link rel="alternate" href="https://www.bruh.ltd/blog/the-rule-of-two-my-housekeeping-principle/"/><content type="html"><![CDATA[
                    <p>Last year, I had a great opportunity to move out and live on my own
for more than half a year. As such, I managed to discover many things
that didn't allow me to live happily before, one of which was my
non-existent daily routine. However, it turned out there was a
solution.</p>











<hgroup>
    <h2 id="backstory">
        Backstory
    </h2>

    <a href="#backstory" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Backstory'</span>
    </a>
</hgroup>



<p>Note: you can safely skip this section.</p>
<p>Houses usually have a lot of things in them. Especially houses in not
quite the richest regions of Russia. The house I was raised in
happened to be possibly one of the worst offenders when it comes to
hoarding useless garbage.</p>
<p>Human brains have limited memory capacity. Especially neurodivergent
brains powering an extremely lazy person. Unfortunately, I'm this
exact kind of person.</p>
<p>As you've probably already guessed where I'm going with this, these 2
things put me in a perpetual loop of losing stuff, mismanaging stuff,
and not doing stuff due to the sheer volume of shit I had to keep in
my head to get through the day. Upon my gradual realization of that, I
also realized the core problem.</p>











<hgroup>
    <h2 id="core-problem">
        Core problem
    </h2>

    <a href="#core-problem" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Core problem'</span>
    </a>
</hgroup>



<p>Having too much choice discourages actually making a good choice. Or
in other words, if you limit the number of ways you can fuck up,
you'll fuck up less.</p>
<p>This principle is one of the core design decisions in many software
products like the Python programming language or virtually any UI
design guideline set released in the last 10 years (or well, at least
on paper). As it turns out, for me, it's also applicable to
housekeeping. I'm probably not the first person to realize that, and
it also probably doesn't work for normal people, but I guess it
shouldn't stop you from attempting it as well.</p>











<hgroup>
    <h2 id="solution">
        Solution
    </h2>

    <a href="#solution" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Solution'</span>
    </a>
</hgroup>



<p>Now with theoretical bullshit out of the way, let's get into
attempting to solve it. Basically speaking, The Rule of Two entails
the following: don't have more than 2 sets of something, and use the
placement of items in your house to encourage yourself to actually put
effort into something.</p>
<p>Here are the ways I used this rule in everyday life:</p>











<hgroup>
    <h2 id="washing-dishes">
        Washing dishes
    </h2>

    <a href="#washing-dishes" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Washing dishes'</span>
    </a>
</hgroup>



<p>I've always sucked at it, and I still do. To avoid that, I always just
used more dishes to cook/eat food instead of cleaning the dirty ones.
This created many weird situations where I'd used 5 different knives
to cut something and made me wash literal mountains of stuff
afterwards.</p>
<p>Don't fucking do that. The easiest way to actually make yourself wash
dishes and avoid this mistake is to have no choice but to wash dishes.
In other words, get yourself 1 plate, 1 fork, 1 spoon, and 1 knife.
Get yourself another set of these items, but hide it away from your
sight in a way that's difficult to undo. This way, you'll have only
one set of usable dishes that need to be washed after use + an
additional set of redundant dishes in case you accidentally break yet
another plate.</p>











<hgroup>
    <h2 id="doing-laundry">
        Doing laundry
    </h2>

    <a href="#doing-laundry" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Doing laundry'</span>
    </a>
</hgroup>



<p>I've always been known for always wearing the same kind of clothes, so
this one came naturally to me. If you have only one set of clothes,
you rarely wash them and end up wearing dirty clothes. If you have a
ton of sets of clothes, you either accumulate mountains of laundry or
pick one set and get the same problem.</p>
<p>There's an easy way out of this: have 2 sets of identical clothes and
swap them weekly, doing laundry right after. You can do it at the same
time as your other weekly routines like cleaning up your house (which
you hopefully do). Let's call this day the Maintenance Day. Mine is on
Friday.</p>
<p>You can also apply the same solution to managing your bathroom and
kitchen towels, bedroom fabrics, etc. It's not like you really need
more than 2 sets of each.</p>











<hgroup>
    <h2 id="vacuuming">
        Vacuuming
    </h2>

    <a href="#vacuuming" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Vacuuming'</span>
    </a>
</hgroup>



<p>Don't. Carpets and rugs can both go fuck themselves. The aesthetic
value and marginal warmth they provide is nothing compared to having
to regularly vacuum them or breathe dust all day long.</p>











<hgroup>
    <h2 id="storage-management">
        Storage management
    </h2>

    <a href="#storage-management" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Storage management'</span>
    </a>
</hgroup>



<p>Limit the number of places you can put your things into. It doesn't
have to be 2, but it's a reasonable number. Avoid buying furniture
that gives you additional storage space, and especially desks with
shelves. This doesn't mean you shouldn't partition your stuff into
meaningful categories, however. Just make it so the things you don't
want to see are right in your face so you don't lose them at the most
inappropriate moment.</p>
<p>Obviously, this solution implies you don't have tons of stuff that
requires the aforementioned storage space. If you do, it may be a wise
decision to reconsider your life choices and eliminate some of them
one way or another.</p>











<hgroup>
    <h2 id="afterword">
        Afterword
    </h2>

    <a href="#afterword" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Afterword'</span>
    </a>
</hgroup>



<p>The same thing can be applied to the management of consumables,
electronics, papers, and probably something I couldn't have thought
of. Use your imagination.</p>
<p>While this principle worked for me, I should warn you that it does
require some determination not to give up and some commitment to
routine. I don't know how to help you with that, but I do know that
this approach will ease your efforts somewhat.</p>

                ]]></content></entry><entry><title>Local shawarma in Russia, reviewed</title><summary>Absolutely nothing surprising.</summary><updated>2023-01-26T00:00:00Z</updated><id>https://www.bruh.ltd/blog/local-shawarma-in-russia-reviewed/</id><link rel="alternate" href="https://www.bruh.ltd/blog/local-shawarma-in-russia-reviewed/"/><content type="html"><![CDATA[
                    <p>Long story short: I recently had to relocate far away from home by
car, which presented me a great opportunity to visit a few Russian
cities and try their local shawarma. Here's what came out of it.</p>











<hgroup>
    <h2 id="omsk">
        Omsk
    </h2>

    <a href="#omsk" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Omsk'</span>
    </a>
</hgroup>



<p>It's a piece of fucking garbage. Don't get me wrong, it wasn't
disgusting to eat it, and it didn't look that unappealing. As a piece
of food, it was a totally acceptable thing you could eat to get some
calories. But as a shawarma, or in other words, a piece of art, it was
a fucking dumpster fire. This taste was definitely worse than anything
I've tried yet with the only exception being that one grill place in
Krasnodar Krai. So in the end, there's only conclusion I can make:
buying a shawarma here is like going to a school canteen for your
birthday party. Don't fucking do it.</p>
<p class="rating">
    

    
    
    

    <span class="given" aria-hidden="true">👎</span>
    <span class="visually-hidden">Rating:</span>

    <span class="explanation">Bad</span>
</p>












<hgroup>
    <h2 id="chelyabinsk">
        Chelyabinsk
    </h2>

    <a href="#chelyabinsk" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Chelyabinsk'</span>
    </a>
</hgroup>



<p>Regular high-quality shawarma comparable to an expensive one in my
city. I was actually pleasantly surprised by it. Can recommend, I
guess?</p>
<p class="rating">
    

    
    
    

    <span class="given" aria-hidden="true">🏅</span>
    <span class="visually-hidden">Rating:</span>

    <span class="explanation">Important</span>
</p>












<hgroup>
    <h2 id="ufa">
        Ufa
    </h2>

    <a href="#ufa" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Ufa'</span>
    </a>
</hgroup>



<p>This shawarma claimed to be Syrian. The cook probably was Syrian, but
I'm not sure if I can say that about the shawarma itself. It was...
okay? The one I tried yesterday was heaven compared to this one, but
it was also miles ahead of the one from Omsk. I'd say it's about of
the same quality as, like, a mediocre shawarma from my city. The same
quality I'd expect from picking a random eatery I've never been to.</p>
<p class="rating">
    

    
    
    

    <span class="given" aria-hidden="true">👍</span>
    <span class="visually-hidden">Rating:</span>

    <span class="explanation">Good</span>
</p>












<hgroup>
    <h2 id="saratov">
        Saratov
    </h2>

    <a href="#saratov" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Saratov'</span>
    </a>
</hgroup>



<p>Okay, this was really fucking weird. The place I bought it at is
called Big Shawarma. The name didn't lie; it was indeed big. And I
don't mean big as in falls apart in your hands, but actually big and
manageable. It had a good selection of ingredients, including my
favorite Korean carrot salad, and 3 sauces. As an icing on the cake,
it was also masterfully assembled. And yet, despite all of that, it
tastes like shit. I don't know how it's even possible. The only
explanation I can find to it is that they used the cheapest
ingredients or something. Anyway, it still tastes better than the one
from Omsk, but can't really match the one from Ufa.</p>
<p class="rating">
    

    
    
    

    <span class="given" aria-hidden="true">👎</span>
    <span class="visually-hidden">Rating:</span>

    <span class="explanation">Bad</span>
</p>












<hgroup>
    <h2 id="volgograd">
        Volgograd
    </h2>

    <a href="#volgograd" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Volgograd'</span>
    </a>
</hgroup>



<p>Just pretend I put the same review as for the one from Ufa. It's the
same shit.</p>
<p class="rating">
    

    
    
    

    <span class="given" aria-hidden="true">👍</span>
    <span class="visually-hidden">Rating:</span>

    <span class="explanation">Good</span>
</p>


                ]]></content></entry><entry><title>An awkward questionnaire</title><summary>Complete this if you have an hour to spare.</summary><updated>2022-04-04T00:00:00Z</updated><id>https://www.bruh.ltd/blog/an-awkward-questionnaire/</id><link rel="alternate" href="https://www.bruh.ltd/blog/an-awkward-questionnaire/"/><content type="html"><![CDATA[
                    <p>The point of this questionnaire is to torture you with awkward
questions in order to find out your unique characteristics as a
person. Potential side effects include discomfort and uncertainty in
your own sanity.</p>











<hgroup>
    <h2 id="general-knowledge">
        General knowledge
    </h2>

    <a href="#general-knowledge" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'General knowledge'</span>
    </a>
</hgroup>



<p>You should answer the questions in this section without looking up the
answers.</p>
<ul>
<li>Is airplane food bad?</li>
<li>What is Obama's last name?</li>
<li>What is the capital of Switzerland?</li>
<li>Who was the first female president of the United States?</li>
<li>When did World War II start?</li>
<li>How many letters are there in the Russian alphabet?</li>
<li>What is the name of Jotaro Kujo's Stand from JoJo's Bizarre
Adventure?</li>
<li>Does the sentence &quot;James while John had had had had had had had had
had had had a better effect on the teacher.&quot; make sense to you?</li>
<li>Does the sentence &quot;The complex houses married and single soldiers
and their families.&quot; make sense to you?</li>
<li>Is the word &quot;folk&quot; pronounced with an &quot;l&quot; sound?</li>
<li>How many days did 1752 have?</li>
<li>What are the colors of the flag of the Seychelles?</li>
</ul>











<hgroup>
    <h2 id="accent">
        Accent
    </h2>

    <a href="#accent" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Accent'</span>
    </a>
</hgroup>



<ul>
<li>Can you pronounce such words as &quot;thick&quot; and &quot;that&quot; as they're
pronounced in the British/American English?</li>
<li>Are the words &quot;wine&quot; and &quot;whine&quot; pronounced the same?</li>
<li>Are the words &quot;pour&quot; and &quot;poor&quot; pronounced the same?</li>
<li>Are the words &quot;ferry&quot; and &quot;fairy&quot; pronounced the same?</li>
<li>Are the words &quot;caught&quot; and &quot;cot&quot; pronounced the same?</li>
<li>Does the word &quot;father&quot; rhyme with &quot;bother&quot;?</li>
<li>Are the words &quot;Mary&quot;, &quot;marry&quot;, and &quot;merry&quot; pronounced the same?</li>
<li>Do the words &quot;trap&quot; and &quot;bath&quot; have the same vowel?</li>
<li>Does the word &quot;bird&quot; have the sound the word &quot;rock&quot; begins with?</li>
<li>Are the words &quot;metal&quot; and &quot;medal&quot; pronounced very similarly?</li>
<li>Does the word &quot;hurry&quot; rhyme with &quot;furry&quot;?</li>
<li>Does the word &quot;about&quot; rhyme with &quot;kaput&quot;?</li>
<li>Does the word &quot;bag&quot; rhyme with &quot;vague&quot;?</li>
<li>Are the words &quot;bath&quot; and &quot;barf&quot; pronounced the same?</li>
<li>Are the words &quot;kin&quot; and &quot;king&quot; pronounced the same?</li>
<li>Are the words &quot;fill&quot; and &quot;feel&quot; pronounced the same?</li>
<li>Are the words &quot;full&quot; and &quot;fool&quot; pronounced the same?</li>
<li>Are the words &quot;back&quot; and &quot;bag&quot; pronounced the same?</li>
<li>Are the words &quot;back&quot; and &quot;buck&quot; pronounced the same?</li>
</ul>











<hgroup>
    <h2 id="pronunciation">
        Pronunciation
    </h2>

    <a href="#pronunciation" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Pronunciation'</span>
    </a>
</hgroup>



<ul>
<li>How do you pronounce the word &quot;data&quot;?</li>
<li>How do you pronounce the word &quot;exactly&quot;?</li>
<li>How do you pronounce the word &quot;lmao&quot;?</li>
<li>How do you pronounce the word &quot;lol&quot;?</li>
<li>How do you pronounce the word &quot;GIF&quot;?</li>
<li>How do you pronounce the word &quot;PNG&quot;?</li>
<li>How do you pronounce the word &quot;WAV&quot;?</li>
<li>How do you pronounce the word &quot;gzip&quot;?</li>
<li>How do you pronounce the word &quot;char&quot; as in <code>char letter = 'a';</code>?</li>
<li>How do you pronounce the word &quot;lib&quot; as in &quot;libinput&quot;?</li>
<li>How do you pronounce the word &quot;src&quot; as in <code>src/main.c</code>?</li>
<li>How do you pronounce the word &quot;var&quot; as in <code>var number = 3;</code></li>
<li>How do you pronounce the word &quot;GNOME&quot;?</li>
<li>How do you pronounce the word &quot;GUI&quot; as in &quot;graphical user interface&quot;?</li>
<li>How do you pronounce the word &quot;Kdenlive&quot;?</li>
<li>How do you pronounce the word &quot;RHEL&quot; as in &quot;Red Hat Enterprise Linux&quot;?</li>
<li>How do you pronounce the word &quot;bin&quot; as in <code>/bin/bash</code>?</li>
<li>How do you pronounce the word &quot;etc&quot; as in <code>/etc/sudo.conf</code>?</li>
<li>How do you pronounce the word &quot;mnt&quot; as in <code>/mnt/usb</code>?</li>
<li>How do you pronounce the word &quot;proc&quot; as in <code>/proc/uptime</code>?</li>
<li>How do you pronounce the word &quot;chmod&quot; as in <code>chmod +x prg</code>?</li>
<li>How do you pronounce the word &quot;env&quot; as in <code>env python</code>?</li>
<li>How do you pronounce the word &quot;grep&quot; as in <code>grep -rl &quot;hello&quot;</code>?</li>
<li>How do you pronounce the word &quot;ls&quot; as in <code>ls /etc</code>?</li>
</ul>











<hgroup>
    <h2 id="brain-function">
        Brain function
    </h2>

    <a href="#brain-function" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Brain function'</span>
    </a>
</hgroup>



<ul>
<li>Are you good at telling apart your emotions?</li>
<li>What languages do you know?</li>
<li>What language do you think in?</li>
<li>Do you have an internal monologue?</li>
<li>Does your internal monologue use your own voice or someone else's?</li>
<li>When you read other people's messages in your head, do you read them
with your internal monologue's voice or the sender's voice?</li>
<li>Do you think you have more than one person in your head?</li>
<li>Do you think you're human?</li>
</ul>











<hgroup>
    <h2 id="aphantasia">
        Aphantasia
    </h2>

    <a href="#aphantasia" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Aphantasia'</span>
    </a>
</hgroup>



<ul>
<li>Can you visualize your own past?</li>
<li>Can you imagine 60 dB of bass being pumped right into your ears?</li>
<li>Imagine a cube.
<ul>
<li>What color is it?</li>
<li>Where is it located?</li>
<li>How is it lit?</li>
</ul>
</li>
<li>Can you imagine the smell of a rotten egg?</li>
<li>Can you imagine the taste of coffee without milk or sugar?</li>
<li>Can you imagine someone cutting the tip of your finger?</li>
<li>Can you imagine someone uncomfortably touching your arm?</li>
<li>Can you imagine being extremely hungry?</li>
<li>Can you imagine being extremely thirsty?</li>
<li>Can you imagine losing balance?</li>
<li>Can you imagine wanting to vomit?</li>
</ul>











<hgroup>
    <h2 id="synesthesia">
        Synesthesia
    </h2>

    <a href="#synesthesia" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Synesthesia'</span>
    </a>
</hgroup>



<ul>
<li>What color is the letter E?</li>
<li>What color is the <a href="https://www.youtube.com/watch?v=1h35qGpDWsQ">note C#</a>?</li>
<li>What gender is the number 6?</li>
<li>When you see someone being kicked, do you feel being kicked too?</li>
<li>What does the word &quot;quizzaciously&quot; taste like?</li>
<li>What does soul music taste like?</li>
</ul>











<hgroup>
    <h2 id="superpowers">
        Superpowers
    </h2>

    <a href="#superpowers" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Superpowers'</span>
    </a>
</hgroup>



<p>Note: don't try to do the actions listed if you either don't know the
answer or the answer is &quot;no.&quot;</p>
<ul>
<li>Can you put your foot behind your head?</li>
<li>Does looking at the Sun not damage your eyes?</li>
<li>Can you see infrared or ultraviolet light?</li>
<li>Can you survive in extreme heat or cold?</li>
<li>Can you multiply two 4 digit numbers in your head without a
calculator?</li>
<li>Can you break a concrete wall with your own hands only?</li>
<li>Can you draw a panorama of a city after only seeing it once?</li>
<li>Can you survive a whole month without sleep?</li>
<li>Can you imagine a 4D object rotating in 4 dimensions?</li>
<li>Can you imagine a color that doesn't exist?</li>
<li>Can you survive getting 10000 volts of electricity applied to your
body?</li>
</ul>











<hgroup>
    <h2 id="gender-and-attraction">
        Gender and attraction
    </h2>

    <a href="#gender-and-attraction" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Gender and attraction'</span>
    </a>
</hgroup>



<ul>
<li>Are you good at telling apart different forms of attraction?</li>
<li>On a scale from 1 to 10, how attracted are you to feminine/masculine
people:
<ul>
<li>Sexually?</li>
<li>Romantically?</li>
<li>Aesthetically?</li>
</ul>
</li>
</ul>

                ]]></content></entry><entry><title>Binary occlusion and its applications</title><summary>A whole page of complete nonsense.</summary><updated>2022-02-23T00:00:00Z</updated><id>https://www.bruh.ltd/blog/binary-occlusion-and-its-applications/</id><link rel="alternate" href="https://www.bruh.ltd/blog/binary-occlusion-and-its-applications/"/><content type="html"><![CDATA[
                    <p>The following article was created as an experiment at writing a whole
page of complete nonsense without using any specialized software.
Everything that appears here is fictitious, and any resemblance of
real people, places, or companies is purely coincidental.</p>
<hr>
<p>Since the dawn of time, humanitarian activities has been the major
obstacle for climate change. However, a solution might have been found
in the most unexpected place possible. Bee sex. Improperly
implemented, destruction of the habitats caused the colossal impedance
in the event chain.</p>











<hgroup>
    <h2 id="onset-of-the-story">
        Onset of the story
    </h2>

    <a href="#onset-of-the-story" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Onset of the story'</span>
    </a>
</hgroup>



<p>While the validity of the theory is yet to be proven, its mere
presence highlights the fact that spiders has been dying one by one
for a very long time. A certain director blaming her customers for
poor reception can be classified as the most important step in mammal
evolution. Monkeys' menstrual cycle is quite an unusual thing to
witness. Every single one of them is already dead. And the thing is
that no one can prove whether such a hurdle is worth being put in
place or not.</p>
<p>The ocean has been quite unstable since 1982, which is what scientists
usually prefer to call &quot;the building escalation process&quot;, which has
been used for our advantage for a long time. The profitability of
human kidneys has been disputed for a very long time, however, the
president of Iraq, John Malkovsy, has called this &quot;utter bullshit.&quot;
Your opinion doesn't matter, everything has already been put into
place and reinforced by the law. The introduction of the locomotive in
1473 caused a great deal of pain; the mix of sodium and potassium
chloride produces a peculiar fire, rigorously enforced, which effects
can be controlled by humming the anthem.</p>











<hgroup>
    <h2 id="is-it-really-the-problem-">
        Is it really the problem?
    </h2>

    <a href="#is-it-really-the-problem-" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Is it really the problem?'</span>
    </a>
</hgroup>



<p>Very specific methods of transportation has been implemented by Adobe,
which caused a major displacement of terrestrial biomes. The princess
has anxiety, but that doesn't seem to affect his consciousness in the
process of killing his favorite ice cream. One way, you can find
certain death; the other way, you can find your own ass. Run away. By
doing that, he took a big shit on the entire oil industry, which I
approve, but no one else acknowledges that there could be better ways
of doing that.</p>
<p>If he decides to uncover the truth, the people would be delighted to
fill in the missing holes (which sort of sounds illegal, but it's
actually not; trust me). Read my previous article if you have a need
to protect your point of view. Giant meteorites from outer space sound
like a good Easter egg, which is completely true, but Microsoft would
be quite unhappy if it was to ever come true. (Okay I actually lied,
but there's no need to retell her statement; all of these expressions
stay hierarchically sound.)</p>
<p>What seems to sound like nonsense actually has deep implications for
the computer industry, which is actively talked about in the media,
but keep in mind it's still all in vein; email as a means of
communication was discontinued in 2046, and it's quite sad. Young
people disregard the law and stay gay, and it's not something Poland
is proud of. Ethnic diversity has been a hot topic in China, which
caused her to write an article about his experience with abortions and
how disabled people are actually quite nice. But keep in mind, that
doesn't mean you should overengineer your code even though it's
written in Rust. He almost beat me to death after I said that, which I
painstakingly recorded in our timetable, which affection was seen as
&quot;sexual harassment&quot; of the whole liberal church industry.</p>











<hgroup>
    <h2 id="scope-of-the-act">
        Scope of the act
    </h2>

    <a href="#scope-of-the-act" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Scope of the act'</span>
    </a>
</hgroup>



<p>&quot;You shall slurp your own semen&quot;, Arial Destruction Project
Association (A.D.P.A) said to their shareholders. Our company
manufactures the majority of the female fetuses that are later
distributed to the majority (384) of the pirates in the Josephine Sea
(located near the Isle of Woman). Acknowledging our ass is likely to
be kicked, we decide to ignore your offer and shame your own
employees, even though they're totally correct and we're not; the
imagery of the movie was quite impressive for 2024, and the most
impressive thing about it is the depiction of the following:</p>
<p>I have no fucking clue who George Washington is. He has only ever
witnessed how well his entrepreneurship was going. Such an attractive
woman should never have been involved in sex work, but it was her
decision, and we must respect that. Such a prediction made the entire
future of the city crumble, which shattered our hopes. I absolutely
despise this man and I wish them all the worst. It is our moral
responsibility to reject all attempts at destroying what we've built
with our hard work. Tho I'm not sure if it's actually the right
decision, but it doesn't matter. Shall you keep doing political work
in this area, make sure people are satisfied, and pretty please, don't
get into the dirty business.</p>
<p>It's truly terrifying how far the plastic has spread. If you enforce
such a rule at its fullest power, even though no one else wants it,
we're basically screwed over; all of the decisions we made and
observations we collected will be lost. Even if they tell us to spy on
you, we will never give up the hope of rejection to apply the best
practices, track how many steps you have walked in your entire life,
search for the best grocery store, or even record the documentary
about wild life in Brazil.</p>
<p><code>git commit</code> is a particularly useless command since no one ever uses
it, but we do use it here at Poop Toilet, Inc. Absolutely no one, not
even Fox Industries, cares what you look like, but we're required by
the law to track such data, and that can mean no one from France will
ever get true satisfaction from their life. The only way to free
yourself of suffering is to sacrifice your soul to the devil.</p>











<hgroup>
    <h2 id="tips-for-content-creators">
        Tips for content creators
    </h2>

    <a href="#tips-for-content-creators" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Tips for content creators'</span>
    </a>
</hgroup>



<p>NFTs, while looking like a scam at first glance, actually are, which
opens a great variety of opportunities to control the market; this
hopefully should make our lives easier by eliminating the middle man
between you and your chair. Once upon a time, this was considered a
fair play, but it no longer is; come to think about it, this is
completely ridiculous, but that's just the world we live in. Old
technologies must be abandoned in favor of more abusive factors of the
environment, however God says you to do. Federalization is the only
way out of this paradise.</p>
<p>It's completely useless to try to resist the urge, let the porridge in
my head surround us nonetheless, giving birth to whole galaxies while
destroying the very nature of being a responsible citizen, and all
that was required was a piece of plastic with no cuts. What? I
honestly don't remember, but it was between 7&quot;5' and 47 km/KiB. You
can do a similar thing by performing a simple life hack: The trick is
to basically ignore everything I've said earlier (which Japanese
people usually call 환영하다 — the rise of the dead). The usage of the
black material called &quot;dirg&quot; managed to hide the very fact that the
drawings has never been shown to anyone. There's no way I can
demonstrate it to you, but trust the spirit, framing several people as
communists will do no good for the foreground scenery.</p>
<p>Fuck you, James Cook. Your achievements have been nothing but a pain
in the ass for the entire human race.</p>

                ]]></content></entry><entry><title>Software I use</title><summary>Or if you're from the future, used to use.</summary><updated>2022-01-09T00:00:00Z</updated><id>https://www.bruh.ltd/blog/software-i-use/</id><link rel="alternate" href="https://www.bruh.ltd/blog/software-i-use/"/><content type="html"><![CDATA[
                    <p>The world of software is quickly changing, so chances are this article
will be irrelevant in a couple of years. I guess this means I'll have
to write another one, but it doesn't matter. If you're from the
present, feel free to judge me for my poor choices, and if you're from
the future, enjoy this little time capsule full of prehistoric
technology.</p>











<hgroup>
    <h2 id="base-system">
        Base system
    </h2>

    <a href="#base-system" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Base system'</span>
    </a>
</hgroup>














<hgroup>
    <h3 id="operating-system-fedora">
        Operating system: Fedora
    </h3>

    <a href="#operating-system-fedora" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Operating system: Fedora'</span>
    </a>
</hgroup>



<p>As you can tell by <a href="/about/rules-i-live-by/">one of the rules I live by</a>, I'm really into
cutting edge technology. This is why I use Arch Lin... Okay I actually
don't. And there are a few reasons for that:</p>
<ul>
<li>Rolling release distros are not stable enough for me. They tend to
break once in a while. And &quot;once in a while&quot; just happens to happen
at the most unexpected and inappropriate moment possible. With fixed
release distros, you can easily tell when the things are going to
break — at the moment of an upgrade.</li>
<li>Fedora has enough packages for me. It doesn't have as much as Ubuntu
or as a diverse range of them as Arch, but it has the exact packages
I need, and they're just fresh enough.</li>
<li>It's supposed to work out of the box, so it's easier to install and
work with. In other words, even though it's not a DIY distro, it
works well for me as one because it's DIY enough for me.</li>
<li>I'm a big Red Hat fan. The community around Red Hat has quite a few
cool and shiny technologies that I like. These include systemd,
GNOME, Wayland, Flatpak, PipeWire, and others. Fedora always has the
latest versions of them and supports them better, so there's no
reason not to use it for me.</li>
</ul>











<hgroup>
    <h4 id="honorable-mentions">
        Honorable mentions
    </h4>

    <a href="#honorable-mentions" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Honorable mentions'</span>
    </a>
</hgroup>



<dl>
<dt>Void Linux</dt>
<dd>What I used to use before Fedora. Not as stable and mainstream but I
guess still usable.</dd>
<dt>CentOS Stream</dt>
<dd>&quot;Fedora LTS.&quot; I use it on my server.</dd>
</dl>











<hgroup>
    <h3 id="desktop-environment-gnome">
        Desktop environment: GNOME
    </h3>

    <a href="#desktop-environment-gnome" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Desktop environment: GNOME'</span>
    </a>
</hgroup>



<p>Yes, I use GNOME. It goes without saying that GNOME is a weird kid on
the block. It's extremely aesthetically minimalist, and the developers
are defending this minimalism as much as possible, which makes a lot
of people angry. In other words, this DE is as far away from Windows
as possible, and people are not used to it.</p>
<p>I, however, really like this minimalism, and this is why I not only
use it but also use it without any extensions. The default GNOME
workflow fits my needs pretty well and requires minimal customization
compared to other desktop environments. The main thing I like about
GNOME is how distraction-free it is. It shows you only so many
elements at once, which works well with my brain that can't handle too
many things at a time. If you're like me in this regard, you'll like
GNOME.</p>








    
        

        

        

        




<hgroup>
    <h4 id="honorable-mentions-2">
        Honorable mentions
    </h4>

    <a href="#honorable-mentions-2" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Honorable mentions'</span>
    </a>
</hgroup>



<dl>
<dt>KDE</dt>
<dd>Good desktop environment for people who like the Windows-like
workflow more.</dd>
<dt>Sway</dt>
<dd>Solid window manager that can be just as good as GNOME for me but
requires a lot of configuration.</dd>
</dl>











<hgroup>
    <h2 id="command-line-applications">
        Command line applications
    </h2>

    <a href="#command-line-applications" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Command line applications'</span>
    </a>
</hgroup>














<hgroup>
    <h3 id="terminal-emulator-khansoul">
        Terminal emulator: <a href="https://gitlab.com/cczp/act-2/khansoul">khansoul</a>
    </h3>

    <a href="#terminal-emulator-khansoul" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Terminal emulator: khansoul'</span>
    </a>
</hgroup>



<p>Well, I wrote it myself as an exercise in writing software without
knowing how it works. I guess that says something.</p>








    
        

        
            
        

        

        

        




<hgroup>
    <h4 id="honorable-mentions-3">
        Honorable mentions
    </h4>

    <a href="#honorable-mentions-3" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Honorable mentions'</span>
    </a>
</hgroup>



<dl>
<dt>XFCE Terminal</dt>
<dd>Good alternative if you don't want to use code written by a Russian
shitcoder.</dd>
<dt>GNOME Terminal</dt>
<dd>Good alternative if you don't mind it being slightly &quot;bloated&quot; and
lacking a few customization options.</dd>
</dl>











<hgroup>
    <h3 id="unix-shell-fish">
        Unix shell: fish
    </h3>

    <a href="#unix-shell-fish" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Unix shell: fish'</span>
    </a>
</hgroup>



<p>Truth be told, I fucking hate shell as a language. It looks like
complete shit, makes it extremely easy to shoot yourself in the foot
(even easier than C does), and makes you produce unreadable code if
you're trying to do something complex. fish sort of fixes those issues
at the cost of not being POSIX-compatible. Luckily though, I don't
give a single damn about POSIX compatibility, so I'm perfectly fine
writing my scripts in it.</p>
<p>Yeah, and it also works out of the box. I still customize it a bit,
but at least it doesn't require me to install 12000 packages to get
basic functionality.</p>








    
        

        
            
        

        
            
        

        

        

        




<hgroup>
    <h4 id="honorable-mentions-4">
        Honorable mentions
    </h4>

    <a href="#honorable-mentions-4" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Honorable mentions'</span>
    </a>
</hgroup>



<dl>
<dt>Python</dt>
<dd>Not a shell but still a good language to write your scripts in.</dd>
<dt>Zsh</dt>
<dd>POSIX-compatible shell that can be customized to work just as well
as fish.</dd>
</dl>











<hgroup>
    <h3 id="text-editor-neovim">
        Text editor: Neovim
    </h3>

    <a href="#text-editor-neovim" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Text editor: Neovim'</span>
    </a>
</hgroup>



<p>When it comes to text editing, I have very specific requirements that
no text editor can achieve out of the box while not being bloated.
Therefore, I have to put myself through the torture of using Neovim,
which is highly customizable but a pain in the ass to get used to.
Luckily, I'm a masochist, so it's absolutely not an issue for me.</p>








    
        

        
            
        

        
            
        

        
            
        

        

        

        




<hgroup>
    <h4 id="honorable-mentions-5">
        Honorable mentions
    </h4>

    <a href="#honorable-mentions-5" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Honorable mentions'</span>
    </a>
</hgroup>



<dl>
<dt>Nano</dt>
<dd>A minimalist text editor that doesn't require you to be a masochist
to use it.</dd>
<dt>Vim</dt>
<dd>Neovim but not neo.</dd>
</dl>











<hgroup>
    <h3 id="version-control-git">
        Version control: git
    </h3>

    <a href="#version-control-git" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Version control: git'</span>
    </a>
</hgroup>



<p>Let's be honest. I have no idea how it works nor do I know how to use
it properly. Still, it somehow manages to be extremely helpful to me.
For me as a programmer wannabe, version control is critical since it
allows me to effectively introduce changes into the code base without
breaking everything. It's a complete miracle that git works so well
despite being so complex and that it managed to become so popular
despite being decentralized and open source. Let's hope it doesn't go
away.</p>








    
        

        
            
        

        
            
        

        
            
        

        
            
        

        

        

        




<hgroup>
    <h4 id="honorable-mentions-6">
        Honorable mentions
    </h4>

    <a href="#honorable-mentions-6" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Honorable mentions'</span>
    </a>
</hgroup>



<dl>
<dt>Controlling your versions manually</dt>
<dd>Sure, why not?</dd>
</dl>











<hgroup>
    <h3 id="file-sync-rclone">
        File sync: rclone
    </h3>

    <a href="#file-sync-rclone" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'File sync: rclone'</span>
    </a>
</hgroup>



<p>rclone is a Swiss army knife utility that allows you to sync from any
cloud storage and to any cloud storage. The fact that such a utility
exists and it's completely open source is a miracle, and I'm so glad
that it does. Now that I know about it, I no longer have to use any
crappy proprietary client for my cloud storage provider and can just
use one little tool for everything, and it just works. Which means
that I get better user experience than even Windows users. Isn't that
wonderful?</p>








    
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        

        

        




<hgroup>
    <h4 id="honorable-mentions-7">
        Honorable mentions
    </h4>

    <a href="#honorable-mentions-7" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Honorable mentions'</span>
    </a>
</hgroup>



<dl>
<dt>rsync</dt>
<dd>For the cases when you need to sync up with your own server.</dd>
<dt>GVfs</dt>
<dd>Similar to rclone but made for slightly different purposes.</dd>
</dl>











<hgroup>
    <h3 id="website-engine-hugo">
        Website engine: Hugo
    </h3>

    <a href="#website-engine-hugo" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Website engine: Hugo'</span>
    </a>
</hgroup>



<p>As you have probably noticed, my website is quite complex. And to
handle such complexity, I have to use a static site generator. Hugo is
the one I randomly chose to be the one I use. So far, it's been quite
a pleasant experience. The template language it uses, while being
slightly weird, allows me to pull off quite a few interesting tricks
like a breadcrumb navigation and anchored headings. Another nice thing
about it is that it's statically linked and written in Go, which means
it's just one binary file with no dependencies.</p>








    
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        

        

        




<hgroup>
    <h4 id="honorable-mentions-8">
        Honorable mentions
    </h4>

    <a href="#honorable-mentions-8" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Honorable mentions'</span>
    </a>
</hgroup>



<dl>
<dt>Not using an SSG</dt>
<dd>Good idea if you have a small website and/or don't mind editing
every single one of your pages after a slight change in the
template.</dd>
<dt>Writing your own custom SSG</dt>
<dd>Good idea if you're unsatisfied with other options and also
extremely smart unlike me.</dd>
</dl>











<hgroup>
    <h2 id="graphical-applications">
        Graphical applications
    </h2>

    <a href="#graphical-applications" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Graphical applications'</span>
    </a>
</hgroup>














<hgroup>
    <h3 id="web-browser-firefox">
        Web browser: Firefox
    </h3>

    <a href="#web-browser-firefox" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Web browser: Firefox'</span>
    </a>
</hgroup>



<p>Yes, Mozilla is not doing well as a company, but Firefox still remains
the one browser that's reasonably private, has enough features, and
supports Linux well enough. If it dies someday, I'll jump to the
second best option, but while it's alive, I'll keep using it. Giving
up and allowing Google to have a monopoly to decide what the Web is
going to be is a bad idea.</p>








    
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        

        

        




<hgroup>
    <h4 id="honorable-mentions-9">
        Honorable mentions
    </h4>

    <a href="#honorable-mentions-9" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Honorable mentions'</span>
    </a>
</hgroup>



<dl>
<dt>Brave</dt>
<dd>Second best option? I'm not sure.</dd>
<dt>Ungoogled Chromium</dt>
<dd>Another good option, I guess, but lacks a few useful features.</dd>
</dl>











<hgroup>
    <h3 id="password-manager-bitwarden">
        Password manager: Bitwarden
    </h3>

    <a href="#password-manager-bitwarden" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Password manager: Bitwarden'</span>
    </a>
</hgroup>



<p>Bitwarden combines the best of the 2 password manager worlds. On one
hand, it's open source, which means you can actually trust it. On the
other hand, it's cloud-based, which allows you to sync your passwords
between devices in a comfortable way without any magic. On top of
that, it also offers a generous free plan that barely has any
limitations and allows you to self-host your own server. For these
reasons, Bitwarden is what I recommend to an average person.</p>








    
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        

        

        




<hgroup>
    <h4 id="honorable-mentions-10">
        Honorable mentions
    </h4>

    <a href="#honorable-mentions-10" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Honorable mentions'</span>
    </a>
</hgroup>



<dl>
<dt>KeepassXC</dt>
<dd>Better option for paranoid people who can sync their stuff manually.</dd>
<dt><a href="https://www.passwordstore.org/">pass</a></dt>
<dd>Better option for extreme minimalists who use the command line in
addition to being able to manually sync stuff.</dd>
</dl>











<hgroup>
    <h3 id="productivity-app-microsoft-to-do">
        Productivity app: Microsoft To-Do
    </h3>

    <a href="#productivity-app-microsoft-to-do" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Productivity app: Microsoft To-Do'</span>
    </a>
</hgroup>



<p>Oh, what's this? A proprietary app? By Microsoft? Yes, it is. I'd
gladly use something else but this app satisfies my note taking needs
perfectly despite being proprietary:</p>
<ul>
<li>It's extremely simple. All I need is an ability to write stuff and a
checkbox near the stuff I wrote. Also maybe an ability to organize
stuff into lists and folders. Nothing else.</li>
<li>It has both an Android app and a web app, which I absolutely 100%
need because I often take notes on my phone.</li>
<li>It syncs my stuff with the cloud, so I never have to do it manually.</li>
</ul>
<p>If you know any other app that is open source and satisfies all of the
3 requirements, feel free to contact me.</p>








    
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        

        

        




<hgroup>
    <h4 id="honorable-mentions-11">
        Honorable mentions
    </h4>

    <a href="#honorable-mentions-11" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Honorable mentions'</span>
    </a>
</hgroup>



<dl>
<dt>Notion</dt>
<dd>Another proprietary app that allows you to organize quite some
complex stuff.</dd>
<dt>A plain text file</dt>
<dd>What I used to use. Doesn't work that bad but doesn't satisfy any of
the 3 requirements.</dd>
</dl>











<hgroup>
    <h3 id="graphical-editor-gimp">
        Graphical editor: GIMP
    </h3>

    <a href="#graphical-editor-gimp" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Graphical editor: GIMP'</span>
    </a>
</hgroup>



<p>GIMP is by far not the best graphical editor in the world, but there
isn't much choice. It's a bit technologically outdated and not the
most powerful, but hey it's open source and actually somewhat works.
In addition to that, it's the only editor I'm good at, so abandoning
it would be not the smartest idea.</p>








    
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        

        

        




<hgroup>
    <h4 id="honorable-mentions-12">
        Honorable mentions
    </h4>

    <a href="#honorable-mentions-12" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Honorable mentions'</span>
    </a>
</hgroup>



<dl>
<dt>ImageMagick</dt>
<dd>Another way to do magic on images but without a GUI.</dd>
<dt>Microsoft Paint</dt>
<dd>Where it all started.</dd>
</dl>











<hgroup>
    <h3 id="office-suite-libreoffice">
        Office suite: LibreOffice
    </h3>

    <a href="#office-suite-libreoffice" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Office suite: LibreOffice'</span>
    </a>
</hgroup>



<p><a href="/blog/things-i-hate-part-2/#wysiwyg-editors">I hate WYSIWYG editors</a> but still have to use this one for my college
stuff. Someday, the good times will come, and I'll no longer have to
use it.</p>








    
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        

        

        




<hgroup>
    <h4 id="honorable-mentions-13">
        Honorable mentions
    </h4>

    <a href="#honorable-mentions-13" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Honorable mentions'</span>
    </a>
</hgroup>



<dl>
<dt>Markdown</dt>
<dd>Use it when you want to write stuff without subjecting yourself to
rectal pain.</dd>
<dt>Microsoft Office</dt>
<dd>Proprietary garbage that works better for some edge cases.</dd>
</dl>











<hgroup>
    <h3 id="video-capture-streaming-obs">
        Video capture/streaming: OBS
    </h3>

    <a href="#video-capture-streaming-obs" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Video capture/streaming: OBS'</span>
    </a>
</hgroup>



<p>Just like git, OBS is a good example of a software miracle. It's open
source, and everyone uses it. The latter is especially weird,
considering it's targeted for gamers, and 99.9% of the video games are
proprietary. Once again, I'm so glad that it exists because otherwise
I'd have to rely on something less professional like CLI-based hacks.</p>








    
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        

        

        




<hgroup>
    <h4 id="honorable-mentions-14">
        Honorable mentions
    </h4>

    <a href="#honorable-mentions-14" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Honorable mentions'</span>
    </a>
</hgroup>



<dl>
<dt>GNOME built-in screen recorder</dt>
<dd>Works well when you need to quickly capture something to show to
other people.</dd>
<dt>FFmpeg</dt>
<dd>For the cases when you need to do some magic on the recorded
video/audio.</dd>
</dl>











<hgroup>
    <h3 id="video-game-emulator-retroarch">
        Video game emulator: RetroArch
    </h3>

    <a href="#video-game-emulator-retroarch" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Video game emulator: RetroArch'</span>
    </a>
</hgroup>



<p>As you probably know, I'm a law-abiding citizen, and I never pirate
any video games, especially ones by Nintendo®. Thus, in order to abide
the law and not pirate the games, I need software that would allow me
to play the legally obtained video games by emulating the console
those game would be legally played on. Luckily, RetroArch does exactly
that for a wide range of consoles. It does sacrifice a bit of overall
quality and is prone to bugs, but eh, it's good enough for me.</p>








    
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        
            
        

        

        

        




<hgroup>
    <h4 id="honorable-mentions-15">
        Honorable mentions
    </h4>

    <a href="#honorable-mentions-15" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Honorable mentions'</span>
    </a>
</hgroup>



<dl>
<dt>Not playing legally obtained video games</dt>
<dd>For people who don't have free time (not me).</dd>
<dt>Installing emulators separately</dt>
<dd>For people who have free time (not me).</dd>
</dl>

                ]]></content></entry><entry><title>ISO 8601: the better date format</title><summary>Simple explanation of what ISO 8601 is and why it's better.</summary><updated>2021-02-26T00:00:00Z</updated><id>https://www.bruh.ltd/blog/iso-8601-the-better-date-format/</id><link rel="alternate" href="https://www.bruh.ltd/blog/iso-8601-the-better-date-format/"/><content type="html"><![CDATA[
                    <p>If you haven't been living under a rock, you've probably heard that
there are different date formats in the world such as the American one
(mm/dd/yyyy) and the European one (dd.mm.yyyy). If you're smart
enough, you've probably also noticed that the American one makes no
sense and is just awful. A simple conclusion that many people draw out
of this is that the European format is the best one, however I don't
think this is true. If you're one of these people who think so, I'm
here to (hopefully) change your mind by introducing you to a
lesser-known date format called ISO 8601.</p>











<hgroup>
    <h2 id="basics">
        Basics
    </h2>

    <a href="#basics" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Basics'</span>
    </a>
</hgroup>



<p>As you can see by the &quot;ISO&quot; part in the format's name, it's an actual
standard written by the International Organization for
Standardization. It defines many cool things like a way to write time
intervals, which can be useful for writing portable software, and a
calendar where the year is separated not by months but by weeks, which
is used in finances, but here we're only interested in the basics.
Simplified, the core date format looks like this:</p>
<pre tabindex="0"><code>yyyy-mm-ddThh:mm:ss
</code></pre><p>RFC 3339, a commonly used profile of ISO 8601, also allows you to
replace the <code>T</code> in the middle with a space, for better readability:</p>
<pre tabindex="0"><code>yyyy-mm-dd hh:mm:ss
</code></pre><p>Yup, that's about it. You write the year, the month, the day, and then
the time exactly like it's done in other date formats. There's nothing
extraordinary, so you can learn it in 2 minutes.</p>











<hgroup>
    <h2 id="why-it-s-better">
        Why it's better
    </h2>

    <a href="#why-it-s-better" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Why it's better'</span>
    </a>
</hgroup>














<hgroup>
    <h3 id="it-s-unambiguous">
        It's unambiguous
    </h3>

    <a href="#it-s-unambiguous" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'It's unambiguous'</span>
    </a>
</hgroup>



<p>This is the main reason the standard was written and why people still
use it. Other date formats can be difficult to tell apart. For
example, consider this date:</p>
<pre tabindex="0"><code>02-03-04
</code></pre><p>When you read it out of context, you have absolutely no idea what's
going on there. Is <code>02</code> here the day or the month? You just can't know
unless the day in the date is greater than 12, in which case it just
can't be a month:</p>
<pre tabindex="0"><code>30-03-04
</code></pre><p>This day-month ambiguity is a really common problem, which often
occurs online. People just write down their dates in whatever date
format they know without even thinking that other people can interpret
it in different ways.</p>
<p>ISO 8601 doesn't have this problem as it's always obvious which part
is the day and which is the month because of the uniqueness of the
format:</p>
<pre tabindex="0"><code>2004-03-02
</code></pre>










<hgroup>
    <h3 id="it-s-more-strict">
        It's more strict
    </h3>

    <a href="#it-s-more-strict" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'It's more strict'</span>
    </a>
</hgroup>



<p>While other date formats usually don't provide strict requirements on
how to write something, ISO 8601 is an exception. Apart from few edge
cases, here, there's only one correct way to write a date, which is
not only useful for computers to parse, but also helpful for humans to
avoid confusion with other formats and improve readability. Here are
some of the restrictions:</p>
<ul>
<li>The elements in the date are always separated by a hyphen. Not many
date formats use this delimiter, and this also can be useful when
using dates inside filenames as slashes are usually not accepted in
them.</li>
<li>The elements are always padded to the maximum number of digits. This
not only makes all of the dates look equally nice, but also, coupled
with other quirks of this format, allows the files with the date in
the name to be sorted just by the filename.</li>
<li>The year is always written in the full form. This makes the format
unique when written down and  eliminates <a href="https://en.wikipedia.org/wiki/Year_2000_problem">the year 2000 problem</a> in
any forms that it can take. For example, when writing down
birthdays, it always makes it obvious which century we're talking
about.</li>
<li>The time is always written in the 24 hour format, so there can be no
confusion about what half of the day something happened in.</li>
</ul>











<hgroup>
    <h3 id="it-makes-more-sense">
        It makes more sense
    </h3>

    <a href="#it-makes-more-sense" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'It makes more sense'</span>
    </a>
</hgroup>



<p>On the first glance, it seems like the European format is about as
logical as it can get — days go into months and months go into years:</p>
<pre tabindex="0"><code>18.12.2002
---------&gt; Elements
</code></pre><p>However, this ignores a very important characteristic of numbers —
endianness. Consider a regular number, for example:</p>
<pre tabindex="0"><code>69420
&lt;---- Digits
</code></pre><p>As you can see the digits here do the opposite of what elements do in
the European format. When the leftmost element of something is the
most valuable, we call it big endian.</p>
<p>Thus, the European format is little endian while the numbers in it are
big endian:</p>
<pre tabindex="0"><code>18.12.2002
&lt;- &lt;- &lt;--- Digits
---------&gt; Elements
</code></pre><p>And the American format just makes no sense:</p>
<pre tabindex="0"><code>12/18/2002
&lt;- &lt;- &lt;--- Digits
?????????? Elements
</code></pre><p>And, as you can see, ISO 8601 is completely consistent in this regard
as everything is big endian:</p>
<pre tabindex="0"><code>2002-12-18
&lt;--- &lt;- &lt;- Digits
&lt;--------- Elements
</code></pre><p>The situation becomes even worse if you consider time because it is
big endian, like ISO 8601, thus doesn't work with any other date
format:</p>
<pre tabindex="0"><code>18.12.2002 23:03:59
&lt;- &lt;- &lt;--- &lt;- &lt;- &lt;- Digits
---------&gt; &lt;------- Elements

12/18/2002 23:03:59
&lt;- &lt;- &lt;--- &lt;- &lt;- &lt;- Digits
?????????? &lt;------- Elements

2002-12-18 23:03:59
&lt;--- &lt;- &lt;- &lt;- &lt;- &lt;- Digits
&lt;--------- &lt;------- Elements
</code></pre><p>If you're still having trouble visualizing all of this in your head,
look at <a href="https://www.reddit.com/r/ISO8601/comments/ln33j2/datetime_format_by_region_visualised_v3_thanks/">this Reddit post</a>.</p>











<hgroup>
    <h3 id="it-s-standardized-and-actively-used">
        It's standardized and actively used
    </h3>

    <a href="#it-s-standardized-and-actively-used" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'It's standardized and actively used'</span>
    </a>
</hgroup>



<p>If you think that ISO 8601 is a silly thing that someone in their
basement made up and no one actually uses, think again because that
can't be further from the truth:</p>
<ul>
<li>The fact that it's standardized says at least something. Does your
favorite format has a neat several hundred page document where it's
described in extreme detail and that is internationally recognized?
Also the standard is quite far from being dead — after being
published in 1988 it was updated in 1991, 2000, 2004, and 2019.</li>
<li>As I already mentioned, the standard is actively used in IT.
Almost everything that is used by software and somehow involves a
written numerical date format already speaks ISO 8601.</li>
<li>yyyy-mm-dd has been adapted or used since the beginning as a
national date format by many countries such as Canada, Sweden, and
Japan. See <a href="https://en.wikipedia.org/wiki/Date_format_by_country">this article</a> for more details.</li>
</ul>











<hgroup>
    <h2 id="frequently-asked-questions">
        Frequently asked questions
    </h2>

    <a href="#frequently-asked-questions" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Frequently asked questions'</span>
    </a>
</hgroup>














<hgroup>
    <h3 id="why-not-use-a-format-like-01-jan-2020-">
        Why not use a format like 01-Jan-2020?
    </h3>

    <a href="#why-not-use-a-format-like-01-jan-2020-" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Why not use a format like 01-Jan-2020?'</span>
    </a>
</hgroup>



<p>It doesn't have any of the nice features ISO 8601 has and doesn't work
well internationally (i.e. assumes the person you're communicating
with knows English). If you think the latter is not a problem, imagine
how you would feel if you had to read a date someone wrote in their
native language that you don't understand:</p>
<pre tabindex="0"><code>01-Янв-2020
</code></pre>










<hgroup>
    <h3 id="yyyy-mm-dd-looks-weird">
        yyyy-mm-dd looks weird
    </h3>

    <a href="#yyyy-mm-dd-looks-weird" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'yyyy-mm-dd looks weird'</span>
    </a>
</hgroup>



<p>The only reason why it does to you is because you're not used to it.
After a little bit of practice, it'll be even less weird than your
favorite date format.</p>











<hgroup>
    <h3 id="maybe-the-european-date-format-is-better-because-the-elements-are-in-the-order-of-relevance-">
        Maybe the European date format is better because the elements are in the  order of relevance?
    </h3>

    <a href="#maybe-the-european-date-format-is-better-because-the-elements-are-in-the-order-of-relevance-" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Maybe the European date format is better because the elements are in the  order of relevance?'</span>
    </a>
</hgroup>



<p>First of all, the claim that the order of relevance is little endian
is quite questionable. The only situation when you can say that for
certain is when we're talking about events occurring on a day-to-day
basis, however I can think of numerous cases when the year and the
month are more relevant:</p>
<ul>
<li>Article publication date</li>
<li>Historical event</li>
<li>Personal event that happened a long time ago</li>
<li>Someone's birthday</li>
<li>Random database entry</li>
</ul>
<p>Second, the order of relevance is actually irrelevant. Even if the
order of relevance was this way, you're not reading the dates out
loud, so there's no need for them to be ordered a certain way. If
you're not interested in the year, you just skip it and read the end
of the date just like you would do when reading time while not being
interested in the hour.</p>








    
        

        
            
        

        

        

        




<hgroup>
    <h2 id="conclusion-3">
        Conclusion
    </h2>

    <a href="#conclusion-3" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Conclusion'</span>
    </a>
</hgroup>



<p>In my opinion, ISO 8601 seems clearly superior to other date formats
when it comes to international communication (such as posting things
online), and as you can see, I have enough reasons to say so. While
the format certainly has an audience, it's unfortunate that it's not
as big as it could be. By writing this article, I hope I made you at
least think about different date formats and be more careful when it
comes to making people understand what date you're talking about.</p>

                ]]></content></entry><entry><title>Controversial things I like</title><summary>Get ready kids, it's actually controversial this time.</summary><updated>2021-02-20T00:00:00Z</updated><id>https://www.bruh.ltd/blog/controversial-things-i-like/</id><link rel="alternate" href="https://www.bruh.ltd/blog/controversial-things-i-like/"/><content type="html"><![CDATA[
                    <p>Now when you know some of the things I hate (<a href="/blog/things-i-hate-part-1/">1</a>, <a href="/blog/things-i-hate-part-2/">2</a>), it's time for
you to know about the things I like. And get ready because this time
they're much more controversial and also sorted in a descending order.</p>











<hgroup>
    <h2 id="content-moderation-on-social-media">
        Content moderation on social media
    </h2>

    <a href="#content-moderation-on-social-media" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Content moderation on social media'</span>
    </a>
</hgroup>



<p>Yes, I'm making a comment on an actual political issue despite being
far from an expert in it. I know it may not turn too well, but I'd
rather be transparent to you.</p>
<p>First, let's clear up a couple of things:</p>
<ul>
<li>I do support free speech, but I acknowledge that it’s not free of
consequences and doesn’t mean a guarantee of a certain way of it to
be presented.</li>
<li>I do still support decentralization despite it making harder to
moderate things as it’s highly beneficial for the democracy and
resisting monopolization.</li>
<li>I think content moderation only makes sense on social media and not
things like cloud providers and DNS registrars as that's too
excessive.</li>
<li>I think the world would be better if social media didn't exist at
all and everyone had their own websites instead as that'd make this
problem much less prevalent and limit the scope of platforms where
content moderation is needed.</li>
<li>While I think offending posts shouldn't be shown, I don't think they
should be deleted forever. Instead, they should be just hidden in a
way that makes it possible to preserve them for future generations
so the history is not lost.</li>
</ul>
<p>So the basic idea of content moderation is that companies employ their
ability to restrict their platform and remove the content they deem
inappropriate. This is allowed to happen because free speech doesn't
apply to private companies, and the people who don't support it are
arguing that it should so the companies are not able to censor any
ideas. I, however, don't support this idea for one simple reason:
it'll do much more harm than benefit us. Aside from being necessary to
limit the conversation from offtopic content, moderation is extremely
useful for eliminating toxicity on the platforms. Even when done
poorly, moderation prevents everything going completely apeshit
because of overflowing by loud hateful vocal minorities. Should you
remove the ability of private companies to do it, <em>every platform</em>
will turn extremely toxic. There would be just no place for a normal
conversation, which will affect the crime rate and will further propel
the spreading of extremist ideologies. This should not be allowed to
happen.</p>
<p>One argument that I've heard against it is &quot;I would rather accept
hateful groups on the platform and let their ideas be challenged by
facts and logic&quot;, however it wouldn't work. No one will give a shit
about facts and logic when they have an advantage of being popular.
There's no other way to get rid of them other than isolate them to
their own platforms, where their ideas slowly decade and die in peace.</p>











<hgroup>
    <h2 id="systemd">
        systemd
    </h2>

    <a href="#systemd" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'systemd'</span>
    </a>
</hgroup>



<p>First of all, if you don't like systemd, I have nothing against either
you or your choice. Just please don't blame me for a choice different
from yours more than I blame you.</p>
<p>In my opinion, systemd is a prime example of a software controversy
made for little to no reason, and it's pretty funny. Here are some of
the common arguments that are used against systemd and why I think
they're wrong:</p>
<ul>
<li>It's monolithic? I have no idea why some people believe it, but
basically they think that systemd is one big fat binary that
encompasses all the features. It's not. The project consists of
several dozen of standalone services that, by the most part, work
independently of each other and can easily be disabled or replaced.
It's quite far away from &quot;all or nothing&quot; and is similar in this
aspect to the Linux kernel.</li>
<li>It's bloated? I'd say that's pretty far from the truth, which can be
proven by looking at the systemd services and the features they
provide. For example, take a look at <a href="https://wiki.archlinux.org/index.php/Systemd-timesyncd">timesyncd</a> or <a href="https://wiki.archlinux.org/index.php/Systemd-networkd">networkd</a>.
That, in my opinion, is quite minimalist and even feature lacking in
some aspects. Projects like <a href="https://chrony.tuxfamily.org/">chrony</a> and <a href="https://wiki.archlinux.org/index.php/NetworkManager">NetworkManager</a> are much
more feature complete, but no one has any complaints to them. And
here I'm not even talking about services like localed or hostnamed
that barely even count as services because they're like 3 lines of
code that don't even sit in the background.</li>
<li>It's complex? Yes, it is technically more complex than previous
projects, but its complexity is justified by its helpful features,
just like for many other software. That's how the modern world
works.</li>
<li>It doesn't follow the Unix way? It uses plain text for
configuration and consists of many small programs that can be used
together to do the job. Sounds pretty Unix to me. But even if it
didn't follow it, let's just admit to ourselves that Unix is dead
for good. What we have now is Linux and we should make the best out
of it and not just blindly follow the principles from a prehistoric
operating system.</li>
<li>It's a feature creep? systemd promises to provide a set of
low-level basic building blocks for a Linux system that allows it to
run and be administered. As you can see, it does what it promises
and nothing more. Just because all those tools are under a single
name doesn't mean it's a feature creep. BSD does the same thing, but
no one complains there.</li>
<li>It forces people to use it? It does but by using the fair technique
of being so useful that people actually use it. No one is
technically holding a gun near your head and forces you to use it,
and you're free to make a systemd-free distro. Just, please, don't
complain when people don't want to support you because they have no
obligation to do so for you.</li>
</ul>
<p>And here are the reasons why I really like it:</p>
<ul>
<li>It's so much more convenient. systemd makes it much easier to do
many things like, for example, reading logs of everything and
analyzing your system. Every instrument is systemd's toolbox has a
uniform well-documented interface that's not that big of a pain to
use.</li>
<li>It's more robust. systemd employs a declarative system for its
configuration, which is more resistant to errors than executing
arbitrary shell commands.</li>
<li>It allows for more clever techniques. One of them, for example, is
socket activation, which allows to launch services on demand instead
just letting them sit in the background forever. Another one is
containerization, which allows you to limit the capabilities of the
services, making them less vulnerable.</li>
<li>It unifies the ecosystem. Now when almost every distro uses systemd
you don't have to worry about making a certain thing just work
across all the systems, because it now just does.</li>
</ul>











<hgroup>
    <h2 id="not-wiping-your-ass">
        Not wiping your ass
    </h2>

    <a href="#not-wiping-your-ass" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Not wiping your ass'</span>
    </a>
</hgroup>



<p>Yes, I am not kidding. Just bear with me.</p>
<p>Wiping your ass with toilet paper is basically the worst thing you can
do to it. Instead of actually getting rid of the feces, you just smear
them while irritating your skin. Considering how people usually wipe,
in the end you're just left with a barely cleaned ass. What's the
solution to this, you might ask? Well, it's obvious — washing it
instead. I've been doing it since I was a child, and I've had
absolutely no problems so far. My ass is about as clean as it can get
and my anal hygiene is incredibly simple while yielding great results.</p>











<hgroup>
    <h2 id="airplane-food">
        Airplane food
    </h2>

    <a href="#airplane-food" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Airplane food'</span>
    </a>
</hgroup>



<p>Disclaimer: I've only ever flown cheap Russian airlines, so I have no
idea about the situation in the rest of the world, but it's probably
even better.</p>
<p>This one is kind of hard to explain because tastes are personal, but
basically I think airplane food is not only good but also superior to
regular food you can get in a restaurant or cook at home. Here are my
extremely subjective reasons:</p>
<ul>
<li>It has a unique taste you can't get anywhere else. Apparently,
because of the high altitude, and dry air the food doesn't taste as
prominent as regular food. You may not like it, but I absolutely
love it. It makes the food taste just so much better for me, and I
would be incredibly happy if there was a way to recreate it at home.</li>
<li>It's given to you in a small portion that's just enough to make you
feel satisfied. You have to make the best out of little things you
have and enjoy them.</li>
<li>It's presented at the best time possible. After you've gone through
all of the nightmare that is modern airport and waited through a
portion of the flight, you get hungry and sad, but then you're given
a little nice present in form of some interesting food. Isn't that
nice?</li>
</ul>











<hgroup>
    <h2 id="modern-uis">
        Modern UIs
    </h2>

    <a href="#modern-uis" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Modern UIs'</span>
    </a>
</hgroup>



<p>By modern UIs, which I like, I mean the current state of app and web
design, where minimalism rules, and by old UIs, which I dislike, I
mean 90s utilitarian <a href="https://en.wikipedia.org/wiki/WIMP_(computing)">WIMP</a> design. The best examples I can give of
them is <a href="https://en.wikipedia.org/wiki/GNOME">GNOME</a> and <a href="https://en.wikipedia.org/wiki/Windows_95">Windows 95</a> respectively. In my opinion the
principles of modern UI design do a much better job in the following
aspects:</p>
<ul>
<li>Being eye candy. In contrast to old UIs, where everything is
composed of ugly static gray uniform blocks, modern UIs greatly
emphasize looking epic. One of the ways this is being done is by
using animations. To me personally, they make using the apps more
smooth and comfortable and create an illusion of the app being
something more than just a couple of pixel surfaces on your screen.</li>
<li>Reduced complexity. In contrast to old UIs, where you can have as
many features as possible, making your menus grow arbitrarily long,
in modern UIs you have to think about making everything fit on the
phone screen. As a result, the designs have to be pretty minimalist
with features abstracted in logical ways. This makes the already
simple apps even less complex and hides the complexity of complex
ones in a clever way.</li>
<li>User friendliness. The days of needing to read a manual to use
software are long gone. Professional software still requires you to
learn it, but it's at least not so bad. Making software accessible
by being obvious is a great thing, and we shouldn't go back.</li>
<li>Less clutter. Modern UIs put a much greater emphasis on whitespace
while old UIs tried to make the interface as compact as possible. In
my opinion, this is a great thing because it makes it much easier to
visually scan the information and makes everything look even nicer.</li>
</ul>











<hgroup>
    <h2 id="modern-music">
        Modern music
    </h2>

    <a href="#modern-music" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Modern music'</span>
    </a>
</hgroup>



<p>First of all, let's get one thing out of the way: I don't think there
is such a thing as &quot;bad music.&quot; Any music has an audience, and as long
as it satisfies someone, it's good. You may not personally like modern
music, but that doesn't make it bad. Yes, even if the music is getting
less complex, you can't call it &quot;objectively bad&quot; because it still
serves its purpose of being listened to.</p>
<p>Second, I think we truly live in a wonderful time in terms of music.
We still have all of the nice genres from the past but we also have
people making new stuff, including in those old genres. The new stuff
does a great favor to the music by exploring the boundaries of what's
possible to do with sounds. So in the end, I think if try hard enough
you'll be able to enjoy <em>some</em> modern music too. For example, I'm a
big jazz fan, but I also like dubstep.</p>











<hgroup>
    <h2 id="star-wars-prequels">
        Star Wars prequels
    </h2>

    <a href="#star-wars-prequels" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Star Wars prequels'</span>
    </a>
</hgroup>



<p>It's widely known that the Star Wars prequels turned out to be not
what was expected from the franchise, but in my opinion, it's not
necessarily a bad thing. First, let's be honest, the quality of the
movies wasn't that bad. Yes, the Episode 1 was a kind of rough start,
but it gets much better in the end, and overall the quality of the
film isn't low. Relatively speaking, you can't call the trilogy &quot;bad.&quot;
It surely isn't as classical as the original trilogy but still is
interesting to watch. Second, this trilogy has a very nice thing that
it shares with the original trilogy — originality. It introduced so
many different characters, places, and concepts, but it still felt
like a Star Wars movie series. The same can't be said about the
sequels though. They lack absolutely any originality and basically
copy the original trilogy in a quite shitty way. For this reason, I
can say that the prequels are not that bad, especially compared to the
sequels.</p>

                ]]></content></entry><entry><title>Things wrong with Wayland</title><summary>There are quite some, but it could be worse.</summary><updated>2020-12-23T00:00:00Z</updated><id>https://www.bruh.ltd/blog/things-wrong-with-wayland/</id><link rel="alternate" href="https://www.bruh.ltd/blog/things-wrong-with-wayland/"/><content type="html"><![CDATA[
                    <p>I, as a person who tries to use cutting edge technology, am a Wayland
user, and ever since I started using it, I haven't been able to get
the thoughts about its problems out of my head. It's time to get this
thing off my chest. Here are the reasons Wayland is still not here:</p>











<hgroup>
    <h2 id="the-main-problem">
        The main problem
    </h2>

    <a href="#the-main-problem" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'The main problem'</span>
    </a>
</hgroup>



<p>You may think that it's the fact that it was decided to move from the
&quot;there's only 1 display server&quot; idea. You're wrong, as that would
invalidate the <a href="https://wayland.freedesktop.org/">core goals</a> of the project — to be just a protocol
that requires implementations.</p>
<p>What can't be denied, however, is the fact that instead of creating a
full-featured &quot;batteries included&quot; set of protocols and a reference
implementation of a library, compositors based on which could compete
with X by being just as feature complete, there was created only a
<a href="https://gitlab.freedesktop.org/wayland/weston" title="weston">simple compositor</a>, which can only satisfy the needs of a kiosk and
not a modern desktop environment. An unofficial version of <a href="https://gitlab.freedesktop.org/wlroots/wlroots/" title="wlroots">such a
library</a> didn't even appear until 2017.</p>











<hgroup>
    <h2 id="the-consequences-it-has">
        The consequences it has
    </h2>

    <a href="#the-consequences-it-has" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'The consequences it has'</span>
    </a>
</hgroup>














<hgroup>
    <h3 id="feature-incompleteness">
        Feature incompleteness
    </h3>

    <a href="#feature-incompleteness" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Feature incompleteness'</span>
    </a>
</hgroup>



<p>After 12 years of development, the implementations of the protocol
still have a series of features incompletely implemented:</p>
<ul>
<li>(Fixed by 2025) Color management<br>
<a href="https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/14">Protocol</a>,
<a href="https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4962">wlroots</a>,
<a href="https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4291">Mutter</a>,
<a href="https://invent.kde.org/plasma/kwin/-/merge_requests/7144">KWin</a></li>
<li>(Fixed by 2024) Variable refresh rate support<br>
<a href="https://github.com/swaywm/wlroots/pull/1987">wlroots</a>,
<a href="https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1154">Mutter</a>,
<a href="https://invent.kde.org/plasma/kwin/-/merge_requests/718">KWin</a></li>
<li>(Fixed by 2024) DRM leasing<br>
<a href="https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/67">Protocol</a>,
<a href="https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/2929">wlroots</a>,
<a href="https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3746">Mutter</a>,
<a href="https://invent.kde.org/plasma/kwin/-/merge_requests/662">KWin</a></li>
<li>Input emulation<br>
<a href="https://gitlab.freedesktop.org/libinput/libei">libei</a>,
<a href="https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/2378">wlroots</a>
(won't fix),
<a href="https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2628">Mutter</a>,
<a href="https://invent.kde.org/plasma/kwin/-/merge_requests/5742">KWin</a></li>
<li>(Fixed by 2023) High bit depth display support<br>
<a href="https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3333">wlroots</a>,
<a href="https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3139">Mutter</a>,
<a href="https://invent.kde.org/plasma/kwin/-/merge_requests/97">KWin</a></li>
<li>(Fixed by 2021) Screencasting<br>
<a href="https://github.com/obsproject/obs-studio/pull/4287">OBS Studio</a></li>
<li>Client-side global hotkey binding<br>
<a href="https://github.com/flatpak/xdg-desktop-portal/pull/711">xdg-desktop-portal</a>,
<a href="https://github.com/emersion/xdg-desktop-portal-wlr/issues/240">wlroots</a>
(stuck in limbo),
<a href="https://gitlab.gnome.org/GNOME/xdg-desktop-portal-gnome/-/issues/47">GNOME</a>,
<a href="https://invent.kde.org/plasma/xdg-desktop-portal-kde/-/merge_requests/80">KDE</a></li>
<li>Nvidia GPU support:
<ul>
<li>(Fixed by 2022) Nvidia <a href="https://github.com/NVIDIA/open-gpu-kernel-modules">not being assholes</a></li>
<li>(Fixed by 2021) <a href="https://download.nvidia.com/XFree86/Linux-x86_64/495.29.05/README/gbm.html">GBM support</a> by the proprietary driver</li>
<li>(Fixed by 2024) Explicit synchronization support<br>
<a href="https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/90">Protocol</a>,
<a href="https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4262">wlroots</a>,
<a href="https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3300">Mutter</a>,
<a href="https://invent.kde.org/plasma/kwin/-/merge_requests/4693">KWin</a></li>
</ul>
</li>
</ul>
<p>As you can see, it's not so many, and the partial fault here is on
clients rather than servers.</p>











<hgroup>
    <h3 id="implementation-difficulty">
        Implementation difficulty
    </h3>

    <a href="#implementation-difficulty" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Implementation difficulty'</span>
    </a>
</hgroup>



<p>On the server side, while it's true that Wayland makes implementing a
display server much easier, implementing a window manager is still a
nightmare. For example, even using a library, you need to write <a href="https://gitlab.freedesktop.org/wlroots/wlroots/-/tree/master/tinywl" title="tinywl">a
thousand lines of code</a> to implement the absolute bare bones
compositor, which won't even support such critical things as damage
tracking, hi-DPI, graphical tablets, multiseat, and any input/output
configuration. X, on the other hand, allows you to write as few as <a href="http://incise.org/tinywm.html" title="tinywm">50
lines of code</a> because it handles most of things such as the ones
listed itself.</p>











<hgroup>
    <h3 id="lack-of-standardization">
        Lack of standardization
    </h3>

    <a href="#lack-of-standardization" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Lack of standardization'</span>
    </a>
</hgroup>



<p>Wayland's <a href="https://gitlab.freedesktop.org/wayland/wayland-protocols/">core set of protocols</a> while covering a wide range things,
doesn't provide ones needed to build a modern desktop environment such
as a desktop shell protocol (to build such things as panels and
launchers), a protocol to simulate input and control windows, a
protocol to control the clipboard, and others, leaving that to the
compositors. While <a href="https://gitlab.freedesktop.org/wlroots/wlr-protocols" title="wlr-protocols">such a set of protocols</a> does exist, it's not
adopted by the majority of the compositors. A similar problem is
happening to <a href="https://github.com/flatpak/xdg-desktop-portal" title="xdg-desktop-portal">the set of protocols</a> required to screenshot, screencast
and remote desktop — the adoption by clients is extremely low. This
makes working with Wayland and debugging it much less flexible and
compositor-dependable than X, and makes developing clients even
harder.</p>











<hgroup>
    <h3 id="lack-of-configurability">
        Lack of configurability
    </h3>

    <a href="#lack-of-configurability" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Lack of configurability'</span>
    </a>
</hgroup>



<p>In contrast to X.org, which has <a href="https://linux.die.net/man/5/xorg.conf">a unified config system</a>, each
Wayland compositor has to implement configuration separately. This
results in not only inconvenience when trying to move the config from
one compositor to another or describing how to configure something,
but also different feature coverage by different compositors. For
example, a compositor may not implement an input configuration such as
scrolling speed or graphical tablet mapping or an output configuration
such as display bit depth. <a href="https://github.com/Hjdskes/cage/issues/138">In some cases</a> the compositor may not even
implement any input configuration, which makes using it extremely
problematic, especially considering such a problem doesn't exist when
using X.</p>











<hgroup>
    <h2 id="conclusion">
        Conclusion
    </h2>

    <a href="#conclusion" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Conclusion'</span>
    </a>
</hgroup>



<p>Considering the listed problems, the Wayland's future doesn't look
that bright. But don't give up hope just yet, as long as we have
projects like wlroots pushing the innovation, not everything is lost!</p>

                ]]></content></entry><entry><title>Hypothetical perfect operating system</title><summary>Non-system programmer's vision of a perfect OS.</summary><updated>2020-07-09T00:00:00Z</updated><id>https://www.bruh.ltd/blog/hypothetical-perfect-operating-system/</id><link rel="alternate" href="https://www.bruh.ltd/blog/hypothetical-perfect-operating-system/"/><content type="html"><![CDATA[
                    <p>I'm not a system programmer, and I don't know what I'm talking about,
so take my ideas with a grain of salt. Also your vision of a perfect
OS can be quite different from mine.</p>











<hgroup>
    <h2 id="basic-requirements">
        Basic requirements
    </h2>

    <a href="#basic-requirements" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Basic requirements'</span>
    </a>
</hgroup>



<p>For obvious reasons, the OS would be open source, 100% DRM and spyware
free, actively developed, and actually useful in its area. It would
also probably follow some of the common software standards (like, for
example, JSON for IPC and command line utilities), use consistent
naming and versioning schemes, and be written in a memory-safe
language.</p>











<hgroup>
    <h3 id="existing-implementations">
        Existing implementations
    </h3>

    <a href="#existing-implementations" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Existing implementations'</span>
    </a>
</hgroup>



<ul>
<li>Most of Linux and BSD systems (partially)</li>
<li>Some of hobbyist systems (partially)</li>
</ul>











<hgroup>
    <h2 id="simple-file-hierarchy">
        Simple file hierarchy
    </h2>

    <a href="#simple-file-hierarchy" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Simple file hierarchy'</span>
    </a>
</hgroup>



<p>Both of the 2 most popular file hierarchies, the Windows NT one and
the Unix one (including whatever is built on top of it), are quite
complicated due to historical reasons. Many of the directories are no
longer used for their intended functionality, and some are practically
duplicated.</p>
<p>A good one would look something like this:</p>
<ul>
<li><code>/</code>
<ul>
<li><code>system/</code>
<ul>
<li><em>Stuff</em></li>
</ul>
</li>
<li><code>users/</code>
<ul>
<li><code>username/</code>
<ul>
<li><em>Stuff</em></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>Where <em>Stuff</em> is:</p>
<ul>
<li><code>apps</code>
<ul>
<li><code>appname</code>
<ul>
<li>Whatever resources the app is supposed to be
installed with</li>
</ul>
</li>
</ul>
</li>
<li><code>resources</code>
<ul>
<li><code>binaries</code></li>
<li><code>libraries</code></li>
<li><code>themes</code></li>
<li>Whatever else can be shared between apps</li>
</ul>
</li>
<li><code>data</code>
<ul>
<li><code>appname</code>
<ul>
<li><code>cache</code></li>
<li><code>config</code></li>
<li>Whatever else state or configuration the app can
have</li>
</ul>
</li>
</ul>
</li>
<li><code>documents</code>, <code>downloads</code>, <code>music</code>, <code>videos</code>, etc</li>
</ul>








    
        

        

        

        




<hgroup>
    <h3 id="existing-implementations-2">
        Existing implementations
    </h3>

    <a href="#existing-implementations-2" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Existing implementations'</span>
    </a>
</hgroup>



<ul>
<li>macOS (kind of)</li>
<li>Flatpak (partially)</li>
</ul>











<hgroup>
    <h2 id="everything-is-an-object">
        Everything is an object
    </h2>

    <a href="#everything-is-an-object" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Everything is an object'</span>
    </a>
</hgroup>



<p>Having a shitton of protocols, for which you often don't have enough
tools to easily explore, is terrible for discoverability. Everything
is a file was supposed to fix that, but the solution was awkward and
hard to deal with. So, instead of pretending that everything is a
file, it'd make sense to accept that some &quot;files&quot; are not actually
files and implement a universal way to explore them.</p>
<p>For example, a scheme could be created for each subsystem of the OS,
allowing access to its objects via a URL like <code>file:/system/apps/</code>.
Here's an example of what schemes could be created:</p>
<ul>
<li><code>file</code> for the root file system and <code>disk</code> for any</li>
<li><code>http{,s}</code>, <code>{quic,tcp,udp}</code>, <code>ip</code> for different levels of
network access</li>
<li><code>process</code> for signals, process information, and some IPC</li>
<li><code>network</code>, <code>settings</code>, <code>audio</code>, <code>video</code>, etc for high-level
configuration/IO</li>
<li><code>tty</code>, <code>desktop</code>, <code>window</code>, <code>notification</code>, etc for UI</li>
<li><code>device</code> for low-level IO</li>
<li>A custom scheme registered by its (in-library or standalone)
handler</li>
</ul>








    
        

        
            
        

        

        

        




<hgroup>
    <h3 id="existing-implementations-3">
        Existing implementations
    </h3>

    <a href="#existing-implementations-3" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Existing implementations'</span>
    </a>
</hgroup>



<ul>
<li>Redox</li>
<li>D-Bus (kind of)</li>
</ul>











<hgroup>
    <h2 id="mandatory-app-sandboxing">
        Mandatory app sandboxing
    </h2>

    <a href="#mandatory-app-sandboxing" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Mandatory app sandboxing'</span>
    </a>
</hgroup>



<p>For obvious security reasons, no app should be ever accepted as 100%
trustworthy and bug-free, and sandboxing never lets that happen. That
is unless there's a way to disable the sandbox or let some apps act
outside of it, which will unavoidably get used, defeating the whole
purpose of sandboxing.</p>
<p>Considering the file hierarchy from the previous point, it'd look
something like this:</p>
<ul>
<li>By default, an app only has access to the <code>file</code> protocol
and can only access its own files (read only), data, and
(shared) resources it needs.</li>
<li>It can ask for access to an additional protocol, resource,
or files/data of another app.</li>
<li>An app can be given a temporary or a permanent permission
for such access.</li>
<li>Each permission request must be approved or disapproved by
the user.</li>
<li>File dialogs are used to acquire permission to files that
the user needs to open.</li>
</ul>








    
        

        
            
        

        
            
        

        

        

        




<hgroup>
    <h3 id="existing-implementations-4">
        Existing implementations
    </h3>

    <a href="#existing-implementations-4" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Existing implementations'</span>
    </a>
</hgroup>



<ul>
<li>Android</li>
<li>Flatpak</li>
<li>OpenBSD</li>
</ul>











<hgroup>
    <h2 id="conclusion">
        Conclusion
    </h2>

    <a href="#conclusion" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Conclusion'</span>
    </a>
</hgroup>



<p>It seems to be reasonable to just improve Linux instead of creating a
whole new OS, and some progress is currently being made.</p>

                ]]></content></entry><entry><title>Things I hate, part 2</title><summary>This time, it's even spicer.</summary><updated>2020-06-27T00:00:00Z</updated><id>https://www.bruh.ltd/blog/things-i-hate-part-2/</id><link rel="alternate" href="https://www.bruh.ltd/blog/things-i-hate-part-2/"/><content type="html"><![CDATA[
                    <p>This time, let's cover a little bit more controversial topics.</p>











<hgroup>
    <h2 id="windows-font-rendering">
        Windows font rendering
    </h2>

    <a href="#windows-font-rendering" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Windows font rendering'</span>
    </a>
</hgroup>



<p>As usual, the elephant in the room. Fonts in Microsoft Windows don't
look as good as they do everywhere else. I know the difference is not
that big, it's all just a matter of preference, and if you're used to
them, they'll look great, but who gives a shit. I'm no font expert,
but here are the problems I can see:</p>
<ul>
<li>The default fonts are not cute enough. Specifically, in my opinion,
the default UI font, <a href="https://en.wikipedia.org/wiki/Segoe#Segoe_UI">Segoe UI</a>, looks like an absolute ass compared
to <a href="https://en.wikipedia.org/wiki/Roboto">Roboto</a>, <a href="https://en.wikipedia.org/wiki/San_Francisco_(sans-serif_typeface)">San Francisco</a>, and even <a href="https://en.wikipedia.org/wiki/Cantarell_(typeface)">Cantarell</a>.</li>
<li>As far as I understand, the fonts are extremely hinted, pushing
every glyph into the pixel boundaries and deforming the intended
design. As far as I know, by default, no other operating system does
that.</li>
<li>Subpixel rendering is used, which while slightly improving the
resolution of the rendered glyphs, distorts their color. In addition
to that, it makes it an absolute pain in the ass to edit the
screenshots and is technically more difficult to implement and
display properly. Most of other modern operating systems don't do
that by default.</li>
</ul>











<hgroup>
    <h2 id="apps-working-only-on-specific-screens">
        Apps working only on specific screens
    </h2>

    <a href="#apps-working-only-on-specific-screens" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Apps working only on specific screens'</span>
    </a>
</hgroup>



<p>Many cancerous proprietary apps nowadays are guilty for this one, and,
holy fuck, I hate it so much. Usually this problem manifests itself in
form of:</p>
<ul>
<li>The app just straight up refusing to switch to the landscape
orientation</li>
<li>The app showing an unclosable error message if you're using it in
the wrong orientation or on the desktop/mobile</li>
<li>The app going apeshit or refusing to work on low resolutions</li>
</ul>
<p>I can kinda understand the last 2 — the developers may be lazy or
greedy as fuck or using some overengineered garbage to build the UI.
An ability to use the app somehow in any case would be nice, but
whatever. The first one, however, just doesn't make any goddamn sense.
If you've built your shit with a modern UI toolkit, there's no way it
can break completely after an orientation switch. Some minor things
can occur if you're building something really complex, but, come on,
you're not <em>that</em> lazy.</p>











<hgroup>
    <h2 id="improper-namespacing">
        Improper namespacing
    </h2>

    <a href="#improper-namespacing" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Improper namespacing'</span>
    </a>
</hgroup>



<p>Or, quite often, the complete lack of it. I'm talking here mostly
about variables in programming languages, but it can also apply to
many other things. Here are some examples:</p>
<dl>
<dt>UNIX shell and classical PHP</dt>
<dd>Everything is just dumped into the global namespace and requires
careful naming.</dd>
<dt>C</dt>
<dd>In addition to the problems of shell/PHP, careful naming is needed
even more due to libraries, and the standard is fucked up (not only
in terms of naming) and extremely long names can (theoretically)
just not work on some compilers.</dd>
<dt>UNIX file hierarchy</dt>
<dd>A lot of not the best naming and duplicated functionality; not that
bad overall, but needs to be simplified.</dd>
<dt>JavaScript</dt>
<dd>Despite opportunities to properly separate everything into modules,
the global namespace is fucking enormous and contains things you
probably don't even know existed.</dd>
<dt>DNS</dt>
<dd>It should've been in reverse.</dd>
</dl>











<hgroup>
    <h2 id="printers">
        Printers
    </h2>

    <a href="#printers" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Printers'</span>
    </a>
</hgroup>



<p>Ink problems aside, we live in the 21st century, so you have no excuse
for not using PDFs instead. Just stop wasting resources.</p>











<hgroup>
    <h2 id="wysiwyg-editors">
        WYSIWYG editors
    </h2>

    <a href="#wysiwyg-editors" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'WYSIWYG editors'</span>
    </a>
</hgroup>



<p>I don't know, they just won't work for me. Complex ones like
{Microsoft ,Libre}Office break everything if you're trying to do
something really sophisticated, while simple ones like your favorite
note taking app are much less useful and rarely compatible with each
other. They also often produce horrendous and barely human-readable
plain text (or even worse, binary) markup, which is a pain in the ass
to correct by hand. It's easier to just use a plain text editor and
type Markdown if you need something simple and HTML+CSS if you need
something cool, which I do.</p>

                ]]></content></entry><entry><title>Things I hate, part 1</title><summary>Spicy content ahead.</summary><updated>2020-05-23T00:00:00Z</updated><id>https://www.bruh.ltd/blog/things-i-hate-part-1/</id><link rel="alternate" href="https://www.bruh.ltd/blog/things-i-hate-part-1/"/><content type="html"><![CDATA[
                    <p>Everyone hates some things, and I'm no exception. You're free to
disagree with me on any point, but I'd be really happy to hear why.</p>











<hgroup>
    <h2 id="bloated-websites">
        Bloated websites
    </h2>

    <a href="#bloated-websites" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Bloated websites'</span>
    </a>
</hgroup>



<p>Let's just start with the elephant in the room, as this website was
heavily inspired by various lightweight ones like <a href="https://bestmotherfucking.website/">Best Motherfucking
Website</a>. At least in my opinion, statically generated and manually
written website show that it's still possible to stay modern or stay
funky without making the browser and server process all of the
unnecessary crap. This website has in total one page that uses
JavaScript, <a href="/extra/credits/">the credits</a>, which is not even a text page but an art
project, and those 10 lines are only used to show a fade-out
animation.</p>
<p>So, yeah, people suck and fuck up everything, including the web, but I
also want to talk about 2 specific websites: <a href="https://www.nytimes.com/">The New York Times</a> and
<a href="https://medium.com/">Medium</a>. Those may be not the best examples, but you get the point:
why the fuck does a website, which sole purpose is to serve text
documents, make my browser have a stroke each time I visit it? This is
just beyond me.</p>











<hgroup>
    <h2 id="not-telling-the-error-message">
        Not telling the error message
    </h2>

    <a href="#not-telling-the-error-message" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Not telling the error message'</span>
    </a>
</hgroup>



<blockquote>
<p>Unexpected error happened. Contact us or something.</p>
</blockquote>
<p>I hate when this happens so much. The anger that I'm experiencing
<em>each time</em> is absolutely indescribable. Look, I understand that your
app aims at the largest audience possible, but is there any specific
reason to <em>not</em> tell me the error message? Don't you think there are
power users that happen to be using your goddamn app? What if the
problem is on my side, how am I supposed to fix it if you don't tell
me anything?</p>
<p>Quite often this problem exist in a form like this:</p>
<blockquote>
<p>Unexpected error 0x0002b375</p>
</blockquote>
<p>Just why? Tell me the motherfucking error message, don't make me
browse your error code listing, which probably won't even help a bit
in the end. It's okay to just print a little bit more text on the
screen, we're not living in the 70s or something, where literally each
bit is precious and must be saved no matter what.</p>











<hgroup>
    <h2 id="voice-messages">
        Voice messages
    </h2>

    <a href="#voice-messages" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Voice messages'</span>
    </a>
</hgroup>



<p>From technical things, let's get more into casual ones. Voice messages
really annoy me, especially when they're received at the worst moment
possible. I know that you're a lazy piece of shit, and you don't even
want to touch your keyboard, but do you really think I'm always ready
to listen to your garbage no matter what? What if, in contrast to you,
I don't want to annoy people in public places with random voices? And
I'm not even talking about voice messages being impossible to search
by their contents, taking more bandwidth, and being more difficult to
archive.</p>
<p>The future would be really better if we had built-in transcription
services in our messengers. That would not only fix all of this shit
but also make them more accessible. Someone, of course, is going to
fuck everything up by putting the whole process in the cloud,
sacrificing users' privacy, instead of doing that locally, but let's
just hope there will be adequate solutions.</p>











<hgroup>
    <h2 id="excessive-punctuation">
        Excessive punctuation
    </h2>

    <a href="#excessive-punctuation" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Excessive punctuation'</span>
    </a>
</hgroup>



<blockquote>
<p>I just walked my dog... That was a good walk... I'm so happy...</p>
</blockquote>
<p>Or even better</p>
<blockquote>
<p>WARNING!!!! Very important information!!!! Don't touch this file!!</p>
</blockquote>
<p>Many of older people (or at least so I think) do that, and I really
want them to stop. I know you may actually be such a slow talker or
scream the whole time, but punctuation exists for a reason.
Exclamation marks and ellipses are made to reflect a change in
intonation to <em>emphasize</em> something. If your whole sentence is
emphasized, then none of it is. Just use periods for fuck's sake.</p>
<p>And if you thought that was bad, wait until you see this:</p>
<blockquote>
<p>Haha)) What a funny joke))))))))))))))))</p>
</blockquote>
<p>You may think that the person has problems with their keyboard, but
it's actually a Russian truncated smiley. So if you have</p>
<blockquote>
<p>Hello :)</p>
</blockquote>
<p>it becomes</p>
<blockquote>
<p>Hello)</p>
</blockquote>
<p>And if you're a complete moron, it becomes</p>
<blockquote>
<p>Hello)))))))))))</p>
</blockquote>
<p>Come on, is it really that hard to just type a singular regular
smiley? No, it's not :) If you use this shit unironically and don't
feel bad about it, I have no faith in you.</p>

                ]]></content></entry><entry><title>The story of GNU/Linux on an unbranded Chinese mini PC</title><summary>How I made a mistake in 2018 and why shouldn't repeat it.</summary><updated>2020-03-22T00:00:00Z</updated><id>https://www.bruh.ltd/blog/the-story-of-gnu-linux-on-an-unbranded-chinese-mini-pc/</id><link rel="alternate" href="https://www.bruh.ltd/blog/the-story-of-gnu-linux-on-an-unbranded-chinese-mini-pc/"/><content type="html"><![CDATA[
                    <p>Sometime in 2018, I decided to buy a $70 Chinese mini PC and use it as
my main machine. As you can see by the price, this wasn't by far the
best decision, but, after intensely torturing both myself and my
machine for some time, I did manage to get the shit working properly.
Here are the steps I had to take to do it:</p>











<hgroup>
    <h2 id="fix-the-intel-graphics-color-range-problems">
        Fix the Intel Graphics color range problems
    </h2>

    <a href="#fix-the-intel-graphics-color-range-problems" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Fix the Intel Graphics color range problems'</span>
    </a>
</hgroup>



<p>This problem became apparent almost instantly, as it was visible as
early as the OS starts to boot up. It manifested itself in form of
washed out colors, especially black. The problem was caused by
improper display color range detection and, according to <a href="https://bugs.freedesktop.org/show_bug.cgi?id=108821">the bug
tracker</a>, was apparently fixed <em>2 times</em>, but the fix still didn't
work on my machine until very recently with kernel version 5.6.0-rc5.
And I'm still not sure if the fix will last.</p>
<p>Update: it didn't.</p>
<p>In any case, after I acknowledged the existence of the problem, the
solution was quickly found on <a href="https://wiki.archlinux.org/index.php/Intel_graphics#Weathered_colors_(color_range_problems)">Arch wiki</a>:</p>
<pre tabindex="0"><code>xrandr --output OUTPUT-DEVICE --set &#39;Broadcast RGB&#39; &#39;Full&#39;
</code></pre><p>And it worked fine until I decided to switch to Wayland. No Wayland
utility I know of provides an ability to set an &quot;output property&quot; yet,
so it took me quite some time to figure out how to do that, and I had
to launch an X server just to fix the problem after each reboot.
Luckily, I bumped into <a href="https://www.brad-x.com/posts/quick-tip-setting-the-color-space-value-in-wayland/">this post</a>. The required utility was called
<code>proptest</code>, and it acted on DRM itself without touching the display
server, so it had to be launched in the framebuffer console. I used
the one from the <code>drm-utils</code> Fedora package and launched it manually
at first but (after failing to make a dracut module) wrapped it in a
systemd service later:</p>
<p><code>/usr/local/lib/systemd/system/broadcast-rgb-workaround.service</code>:</p>
<pre tabindex="0"><code>[Unit]
Description=Work around the broken Broadcast RGB detection

[Service]
Type=oneshot
ExecStart=/usr/local/bin/broadcast-rgb-workaround

[Install]
WantedBy=basic.target
</code></pre><p><code>/usr/local/bin/broadcast-rgb-workaround</code>:</p>
<pre tabindex="0"><code>#!/bin/sh

chvt 12

proptest CONNECTOR-NUMBER connector 97 1

chvt 1
</code></pre><p>(The numbers may alternate, and they did one time, so they have to be
looked up manually by just launching <code>proptest</code>.)</p>











<hgroup>
    <h2 id="fix-the-broken-wifi">
        Fix the broken WiFi
    </h2>

    <a href="#fix-the-broken-wifi" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Fix the broken WiFi'</span>
    </a>
</hgroup>



<p>The solution to this was found almost instantly by searching the
kernel error message. I just had to copy <a href="https://raw.githubusercontent.com/RPi-Distro/firmware-nonfree/master/brcm/brcmfmac43455-sdio.txt">this random firmware file</a>
to <code>/usr/lib/firmware/brcm/</code>.</p>











<hgroup>
    <h2 id="fix-the-broken-audio">
        Fix the broken audio
    </h2>

    <a href="#fix-the-broken-audio" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Fix the broken audio'</span>
    </a>
</hgroup>



<p>The sound card on this machine is called <code>bytcr-rt5651</code>, and it was a
huge pain in the ass to fix. First off, I just refused to use
PulseAudio for quite some time. I'm not entirely sure what my motives
were, but I just accepted having no sound at all. Why it didn't work
with just bare ALSA is a whole other question. When I decided that
there's actually nothing wrong with PulseAudio, the problems didn't
end and it took me some time to find <a href="https://github.com/plbossart/UCM/tree/master/bytcr-rt5651">this set of files</a> and apply it
properly. One problem was that some UCM files were already included by
default, but they were less correct than the ones in the set.</p>
<p>But that fixed only the software problems, and the hardware problems
were much more ridiculous. The 4.5 mm audio jack on this machine acts
as a headphone jack and a microphone jack at the same time.
<strong>Literally at the same</strong>. Plugging the headphones there almost made
me shit my pants the first time as I heard my own movement sounds
amplified. But before I even thought of plugging the headphones
directly, I used a female-to-male jack adapter, which I didn't even
realize was dead. How stupid could I be to not check it for such a
long time. In any case, I just found another one and plugged my
headphones with it.</p>
<p>But then my headphones died. The only options available were the
full-blown speakers and the Bluetooth headphones. The first option
wasn't actually an option because the machine doesn't have enough
horsepower to power them, so I went for the second one and failed.
Bluetooth is supported by this machine and I could even detect the
headphones and connect them, but no audio played whatever I tried. I
didn't have much time to do anything with it, so I gave up for some
time and had no sound once again.</p>
<p>After some time, I suddenly remembered that I had another, very big
compared to the machine itself, speakers with amplification. The idea
looked kinda silly because the speakers are literally, like, ten times
the volume of the PC, and my setup was already fucked up through the
roof, so introducing another cable didn't sound too great. I didn't
have much choice, so I went for it in any case, and everything's been
(mostly) okay since.</p>











<hgroup>
    <h2 id="-mostly-fix-the-c-state-transition-freeze">
        (Mostly) fix the C-State transition freeze
    </h2>

    <a href="#-mostly-fix-the-c-state-transition-freeze" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled '(Mostly) fix the C-State transition freeze'</span>
    </a>
</hgroup>



<p>Intel Atom x5-Z8350 used on this machine, in addition to being a slow
piece of shit and having graphical problems, is vulnerable to freezing
on certain <a href="https://en.wikipedia.org/wiki/Advanced_Configuration_and_Power_Interface#Processor_states">C-State</a> transitions (see <a href="https://bugzilla.kernel.org/show_bug.cgi?id=109051">this bug report</a>). And it seems
like other operating systems like Windows are also affected by this,
but I couldn't test that because I didn't use Windows on this machine
for longer than 10 minutes.</p>
<p>The most common solution for this kind of problem is to use <a href="https://bugzilla.kernel.org/attachment.cgi?id=223851">this
script</a>, but it doesn't work. Adding <code>intel_idle.max_cstate=1</code> to the
kernel boot parameters also doesn't help, but adding
<code>intel_idle.max_cstate=0</code> (which disables <code>intel_idle</code> as a whole and
switches to <code>acpi_idle</code>) appears to work. It seems like it doesn't
completely eliminate freezing, but it happens less often, and
<em>permanent</em> freezing almost doesn't happen. Overall, this issue is not
solved yet, and I'm still looking for updates.</p>








    
        

        
            
        

        
            
        

        

        

        




<hgroup>
    <h2 id="conclusion-4">
        Conclusion
    </h2>

    <a href="#conclusion-4" class="heading-anchor">
        <span aria-hidden="true">#</span>
        <span class="visually-hidden">Section titled 'Conclusion'</span>
    </a>
</hgroup>



<p>I hugely fucked up by buying this computer, and I hope you won't
repeat my mistakes. Everything, however, is not that bad after all
because of the incredible work of the developers of the Linux kernel,
wl-roots, GTK, Firefox, and others, and things are probably going to
get even better. I'm still going to use this machine for some time,
but I will choose my next one more carefully.</p>

                ]]></content></entry><entry><title>Hello, World?</title><summary>First blogpost.</summary><updated>2020-02-11T00:00:00Z</updated><id>https://www.bruh.ltd/blog/hello-world/</id><link rel="alternate" href="https://www.bruh.ltd/blog/hello-world/"/><content type="html">
                    &lt;p>I'm not entirely sure what I'm going to publish here, but here it is.&lt;/p>

                </content></entry></feed>