<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Notes on 7nolikov | Dmitrii Novikov</title><link>https://7nolikov.dev/notes/</link><description>Recent content in Notes on 7nolikov | Dmitrii Novikov</description><generator>Hugo</generator><language>en-US</language><managingEditor>7nolikov@gmail.com (Dmitrii Novikov)</managingEditor><webMaster>7nolikov@gmail.com (Dmitrii Novikov)</webMaster><copyright>Dmitrii Novikov</copyright><lastBuildDate>Sun, 13 Sep 2026 06:02:10 -0700</lastBuildDate><atom:link href="https://7nolikov.dev/notes/index.xml" rel="self" type="application/rss+xml"/><item><title>100 Go Mistakes</title><link>https://7nolikov.dev/notes/100-go-mistakes/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/100-go-mistakes/</guid><description>&lt;p&gt;A catalogue of the mistakes Go developers actually make, with the reasoning behind each one. Free to read online, and also a book.&lt;/p&gt;
&lt;p&gt;The value is not the individual gotchas. It&amp;rsquo;s that most of them cluster around a few themes: slices sharing backing arrays, loop variable capture, goroutine lifetimes nobody owns, and interfaces holding a nil pointer that is not &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Read it once early and you will recognise the shapes later, which is the whole point.&lt;/p&gt;</description></item><item><title>An interactive intro to CRDTs</title><link>https://7nolikov.dev/notes/crdts-interactive-intro/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/crdts-interactive-intro/</guid><description>&lt;p&gt;CRDTs explained with widgets you can drag around, which is the only way this subject has ever made sense to me.&lt;/p&gt;
&lt;p&gt;The core idea: design your data type so that merges are commutative, associative and idempotent. Then two replicas that saw the same edits in different orders end up identical, and you do not need a server to arbitrate.&lt;/p&gt;
&lt;p&gt;You build up from a counter to a set to collaborative text, and each step shows why the naive version breaks first.&lt;/p&gt;</description></item><item><title>Architecture Antipatterns</title><link>https://7nolikov.dev/notes/architecture-antipatterns/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/architecture-antipatterns/</guid><description>&lt;p&gt;A catalogue of architecture antipatterns, each with the symptoms, why people end up there, and what to do instead.&lt;/p&gt;
&lt;p&gt;Useful in the specific moment where you can feel a design is wrong but cannot name it yet. Having the name makes the argument possible - it is much easier to say &amp;ldquo;this is a distributed monolith&amp;rdquo; than to describe the smell from scratch in a meeting.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://architecture-antipatterns.tech/"&gt;architecture-antipatterns.tech&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;See also:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://7nolikov.dev/notes/modular-monolith-primer/" class="backlink"&gt;Modular Monolith: a primer&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://7nolikov.dev/notes/software-architecture-premier/" class="backlink"&gt;Software Architecture Premier&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Caddy</title><link>https://7nolikov.dev/notes/caddy/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/caddy/</guid><description>&lt;p&gt;A web server that gets HTTPS right by default. Point it at a domain and it obtains and renews the certificate itself, with no cron job and no certbot.&lt;/p&gt;
&lt;p&gt;A whole reverse proxy config is two lines:&lt;/p&gt;
&lt;figure class="codeblock not-prose relative scroll-mt-8" id="codeblock-01"&gt;
 &lt;aside
 class="absolute right-0 top-0 hidden rounded-bl-sm rounded-tr-sm bg-white/10 px-2 py-1 text-white/70 transition-opacity md:inline-block"
 &gt;
 &lt;div class="codeblock-meta flex max-w-xs flex-row items-center space-x-3"&gt;
 &lt;div class="small-caps shrink cursor-default truncate font-mono text-xs" aria-hidden="true"&gt;
 &lt;span class="relative"&gt;&lt;/span&gt;
 &lt;/div&gt;
 &lt;div&gt;
 &lt;clipboard-copy
 type="button"
 aria-label="Copy code to clipboard"
 title="Copy code to clipboard"
 class="block cursor-pointer transition-colors hover:text-sky-400"
 target="#codeblock-01 code"
 &gt;
 &lt;svg
 xmlns="http://www.w3.org/2000/svg"
 fill="none"
 stroke="currentColor"
 stroke-width="2"
 stroke-linecap="round"
 stroke-linejoin="round"
 class="lucide lucide-clipboard h-4 w-4"
 viewBox="0 0 24 24"
&gt;
 &lt;rect width="8" height="4" x="8" y="2" rx="1" ry="1" /&gt;
 &lt;path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2" /&gt;
&lt;/svg&gt;

 &lt;/clipboard-copy&gt;
 &lt;/div&gt;
 &lt;div&gt;
 &lt;a
 href="#codeblock-01"
 class="block"
 aria-label="Link to this code block"
 title="Link to this code block"
 &gt;
 &lt;svg
 xmlns="http://www.w3.org/2000/svg"
 width="16"
 height="16"
 fill="none"
 stroke="currentColor"
 stroke-linecap="round"
 stroke-linejoin="round"
 stroke-width="2"
 class="lucide lucide-link w-4 h-4 block"
 viewBox="0 0 24 24"
&gt;
 &lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" /&gt;
 &lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" /&gt;
&lt;/svg&gt;

 &lt;/a&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 &lt;/aside&gt;
 &lt;p class="sr-only"&gt; code snippet start&lt;/p&gt;</description></item><item><title>CMU 15-721 Advanced Database Systems</title><link>https://7nolikov.dev/notes/cmu-advanced-database-systems/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/cmu-advanced-database-systems/</guid><description>&lt;p&gt;Andy Pavlo&amp;rsquo;s graduate course on modern database internals, free on the course site with all lectures on YouTube.&lt;/p&gt;
&lt;p&gt;This is the in-memory, multi-core, storage-engine end of the subject: MVCC, lock-free indexes, query compilation, vectorised execution, columnar layouts. Not &amp;ldquo;how to use Postgres&amp;rdquo; - how the thing is built.&lt;/p&gt;
&lt;p&gt;If you have ever wondered why an OLAP engine and an OLTP engine make opposite choices about literally everything, this is the course that answers it.&lt;/p&gt;</description></item><item><title>Command Line Interface Guidelines</title><link>https://7nolikov.dev/notes/cli-guidelines/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/cli-guidelines/</guid><description>&lt;p&gt;An opinionated guide to designing command line tools that people can actually use.&lt;/p&gt;
&lt;p&gt;Concrete and immediately applicable: respect &lt;code&gt;--help&lt;/code&gt;, exit non-zero on failure, write errors to stderr and results to stdout, don&amp;rsquo;t emit colour when piped, confirm before doing something destructive, and make the tool work in a script as well as in a terminal.&lt;/p&gt;
&lt;p&gt;The section on output is the one I&amp;rsquo;d hand to anybody writing an internal tool. Most CLI pain is a program that prints a friendly progress animation into a log file.&lt;/p&gt;</description></item><item><title>Distroless container images</title><link>https://7nolikov.dev/notes/distroless/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/distroless/</guid><description>&lt;p&gt;Base images containing your application and its runtime dependencies, and nothing else. No shell, no package manager, no utilities.&lt;/p&gt;
&lt;p&gt;The trade-off against Alpine, which is the usual alternative:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Distroless&lt;/strong&gt; has the smaller attack surface - with no shell in the image, a lot of privilege escalation and post-exploitation techniques simply have nothing to run. The static variant is around 2MB. The cost is debugging: you cannot exec in and look around, because there is nothing to exec. In Kubernetes you attach an ephemeral container instead.&lt;/p&gt;</description></item><item><title>Dokku - a small PaaS on your own box</title><link>https://7nolikov.dev/notes/dokku/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/dokku/</guid><description>&lt;p&gt;&lt;code&gt;git push&lt;/code&gt; to your own server and it builds, containerises and runs your app behind a reverse proxy with a TLS certificate. Heroku&amp;rsquo;s workflow on a VPS you control.&lt;/p&gt;
&lt;p&gt;It handles the parts that are tedious to assemble by hand: buildpack or Dockerfile detection, environment variables, zero-downtime restarts, database plugins, Let&amp;rsquo;s Encrypt.&lt;/p&gt;
&lt;p&gt;One thing to know before you commit: Dokku officially supports Debian and Ubuntu LTS. Pairing it with an immutable container OS looks appealing and does not work - Dokku installs via apt and owns nginx and the container lifecycle, which is exactly what an immutable OS refuses to let it do.&lt;/p&gt;</description></item><item><title>endoflife.date</title><link>https://7nolikov.dev/notes/endoflife-date/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/endoflife-date/</guid><description>&lt;p&gt;End-of-life and support dates for hundreds of things - languages, runtimes, databases, distros, frameworks.&lt;/p&gt;
&lt;p&gt;Answers the question you always need before an upgrade argument: is this version still supported, and when does it stop being supported. There is an API and a CLI, so you can wire it into CI and fail a build when a dependency goes out of support.&lt;/p&gt;
&lt;p&gt;Unglamorous and I use it more than most tools I could name.&lt;/p&gt;</description></item><item><title>Go's synctest - deterministic concurrency tests</title><link>https://7nolikov.dev/notes/go-synctest/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/go-synctest/</guid><description>&lt;p&gt;&lt;code&gt;synctest&lt;/code&gt; gives concurrent Go tests a fake clock and a way to wait until every goroutine in a bubble is blocked.&lt;/p&gt;
&lt;p&gt;This kills the worst pattern in Go testing: &lt;code&gt;time.Sleep(100 * time.Millisecond)&lt;/code&gt; scattered through tests to &amp;ldquo;let things settle&amp;rdquo;. Those sleeps make suites slow and flaky at the same time - too short on a loaded CI runner, too long everywhere else.&lt;/p&gt;
&lt;p&gt;With synctest a one-hour timeout test runs instantly and deterministically, because the clock only moves when nothing is left to do.&lt;/p&gt;</description></item><item><title>Grep by example</title><link>https://7nolikov.dev/notes/grep-by-example/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/grep-by-example/</guid><description>&lt;p&gt;An interactive guide to grep - every example runs in the browser, so you try the flag instead of reading about it.&lt;/p&gt;
&lt;p&gt;Worth an hour even if you have used grep for a decade. The parts most people never learned: &lt;code&gt;-o&lt;/code&gt; to print only the match, &lt;code&gt;-A&lt;/code&gt;/&lt;code&gt;-B&lt;/code&gt;/&lt;code&gt;-C&lt;/code&gt; for context lines, &lt;code&gt;-r&lt;/code&gt; with &lt;code&gt;--include&lt;/code&gt;, and when to reach for &lt;code&gt;-P&lt;/code&gt; instead of fighting basic regex syntax.&lt;/p&gt;
&lt;p&gt;Same author has one for ripgrep, which is the same idea and much faster on large trees.&lt;/p&gt;</description></item><item><title>Hurl - HTTP requests as plain text</title><link>https://7nolikov.dev/notes/hurl/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/hurl/</guid><description>&lt;p&gt;Write HTTP requests in a plain text file, run them, assert on the responses. Built on curl.&lt;/p&gt;
&lt;figure class="codeblock not-prose relative scroll-mt-8" id="codeblock-01"&gt;
 &lt;aside
 class="absolute right-0 top-0 hidden rounded-bl-sm rounded-tr-sm bg-white/10 px-2 py-1 text-white/70 transition-opacity md:inline-block"
 &gt;
 &lt;div class="codeblock-meta flex max-w-xs flex-row items-center space-x-3"&gt;
 &lt;div class="small-caps shrink cursor-default truncate font-mono text-xs" aria-hidden="true"&gt;
 &lt;span class="relative"&gt;hurl&lt;/span&gt;
 &lt;/div&gt;
 &lt;div&gt;
 &lt;clipboard-copy
 type="button"
 aria-label="Copy code to clipboard"
 title="Copy code to clipboard"
 class="block cursor-pointer transition-colors hover:text-sky-400"
 target="#codeblock-01 code"
 &gt;
 &lt;svg
 xmlns="http://www.w3.org/2000/svg"
 fill="none"
 stroke="currentColor"
 stroke-width="2"
 stroke-linecap="round"
 stroke-linejoin="round"
 class="lucide lucide-clipboard h-4 w-4"
 viewBox="0 0 24 24"
&gt;
 &lt;rect width="8" height="4" x="8" y="2" rx="1" ry="1" /&gt;
 &lt;path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2" /&gt;
&lt;/svg&gt;

 &lt;/clipboard-copy&gt;
 &lt;/div&gt;
 &lt;div&gt;
 &lt;a
 href="#codeblock-01"
 class="block"
 aria-label="Link to this code block"
 title="Link to this code block"
 &gt;
 &lt;svg
 xmlns="http://www.w3.org/2000/svg"
 width="16"
 height="16"
 fill="none"
 stroke="currentColor"
 stroke-linecap="round"
 stroke-linejoin="round"
 stroke-width="2"
 class="lucide lucide-link w-4 h-4 block"
 viewBox="0 0 24 24"
&gt;
 &lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" /&gt;
 &lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" /&gt;
&lt;/svg&gt;

 &lt;/a&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 &lt;/aside&gt;
 &lt;p class="sr-only"&gt;hurl code snippet start&lt;/p&gt;</description></item><item><title>Kubernetes Failure Stories</title><link>https://7nolikov.dev/notes/kubernetes-failure-stories/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/kubernetes-failure-stories/</guid><description>&lt;p&gt;A collected list of public post-mortems from companies running Kubernetes in production. Real outages, written up by the people who were on call.&lt;/p&gt;
&lt;p&gt;It is the best argument I know against learning a platform only from its documentation. The docs tell you what the system does. These tell you what it does at 3am when a node&amp;rsquo;s disk fills up, a CNI plugin misbehaves, or a &lt;code&gt;livenessProbe&lt;/code&gt; restarts a healthy pod into an outage.&lt;/p&gt;</description></item><item><title>Learn Go with Tests</title><link>https://7nolikov.dev/notes/learn-go-with-tests/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/learn-go-with-tests/</guid><description>&lt;p&gt;Learn Go by writing tests first. Every chapter is a red-green-refactor cycle, and by the end you have covered concurrency, generics, &lt;code&gt;context&lt;/code&gt;, and a couple of real applications.&lt;/p&gt;
&lt;p&gt;It works because the test comes before the explanation. You feel the problem, then the language feature lands as a solution rather than a fact to memorise.&lt;/p&gt;
&lt;p&gt;Best free Go resource I know for someone who can already program.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/quii/learn-go-with-tests"&gt;github.com/quii/learn-go-with-tests&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;See also:&lt;/p&gt;</description></item><item><title>MADR - architecture decision records</title><link>https://7nolikov.dev/notes/madr-architecture-decision-records/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/madr-architecture-decision-records/</guid><description>&lt;p&gt;A markdown template for recording architecture decisions: the context, the options, what was chosen, and the consequences accepted.&lt;/p&gt;
&lt;p&gt;One file per decision, numbered, living in the repo next to the code. The value is not the decision - it is the &lt;em&gt;rejected alternatives&lt;/em&gt;. Six months later the question is never &amp;ldquo;what did we pick&amp;rdquo;, it is &amp;ldquo;why didn&amp;rsquo;t we do the obvious thing&amp;rdquo;, and without a record you re-litigate it from scratch.&lt;/p&gt;</description></item><item><title>Modular Monolith: a primer</title><link>https://7nolikov.dev/notes/modular-monolith-primer/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/modular-monolith-primer/</guid><description>&lt;p&gt;Kamil Grzybek on the middle option between a big ball of mud and a fleet of services.&lt;/p&gt;
&lt;p&gt;The argument that lands: microservices give you module boundaries by making them physical - you cannot accidentally call into another module&amp;rsquo;s database over HTTP without noticing. But you pay for that with a network between every part of your system, and you pay in latency, partial failure and deployment machinery.&lt;/p&gt;
&lt;p&gt;A modular monolith tries to get the boundaries without the network, which means the boundaries have to be enforced some other way - by tests, by build rules, by discipline. That is the whole difficulty, and this piece is honest about it.&lt;/p&gt;</description></item><item><title>NATS</title><link>https://7nolikov.dev/notes/nats/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/nats/</guid><description>&lt;p&gt;A messaging system that covers request/reply, pub/sub and queue groups in one small server, with JetStream adding persistence and streams when you need them.&lt;/p&gt;
&lt;p&gt;Where it differs from Kafka: NATS core is fire-and-forget and extremely light - a single binary, microsecond latencies, no ZooKeeper-era operational weight. Kafka is a durable, replayable log first, and everything else second.&lt;/p&gt;
&lt;p&gt;So the question is not which is better, it&amp;rsquo;s whether you need a log you can replay from an arbitrary offset months later. If you do, use a log. If you are moving messages between services right now, NATS is a fraction of the operational cost.&lt;/p&gt;</description></item><item><title>Reproducible Builds</title><link>https://7nolikov.dev/notes/reproducible-builds/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/reproducible-builds/</guid><description>&lt;p&gt;A set of practices for making a build produce a bit-for-bit identical artifact every time from the same source.&lt;/p&gt;
&lt;p&gt;The reason it matters is supply chain: if the binary you ship cannot be reproduced from the source you published, nobody - including you - can verify that the two correspond. Reproducibility turns &amp;ldquo;trust the build server&amp;rdquo; into something checkable by anyone.&lt;/p&gt;
&lt;p&gt;The things that break it are mundane and everywhere: embedded timestamps, absolute paths, locale, filesystem ordering, and anything that hashes a map iterated in random order. The site catalogues each one and how to fix it.&lt;/p&gt;</description></item><item><title>Saga pattern</title><link>https://7nolikov.dev/notes/saga-pattern/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/saga-pattern/</guid><description>&lt;p&gt;How to keep data consistent across services when you cannot hold a transaction across them.&lt;/p&gt;
&lt;p&gt;The idea: break the operation into local transactions, and give each one a compensating action that undoes it. If step three fails, you run the undo for two and one. There is no rollback - there is only doing something else that cancels out the effect.&lt;/p&gt;
&lt;p&gt;The part people underestimate is that compensation can fail too. Deleting the object you just wrote can return an error, and then you have an orphan and need to notice it. Any real implementation needs a metric on that path and something that reconciles what got stranded.&lt;/p&gt;</description></item><item><title>System Design Primer</title><link>https://7nolikov.dev/notes/system-design-primer/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/system-design-primer/</guid><description>&lt;p&gt;The open-source collection people actually mean when they say &amp;ldquo;go read the system design primer&amp;rdquo;. Caching, sharding, replication, load balancing, CAP, back-of-envelope numbers, then worked examples of designing well-known systems.&lt;/p&gt;
&lt;p&gt;The part I would not skip is the latency numbers table - memory reference vs SSD read vs a round trip between datacenters, in nanoseconds. Once those orders of magnitude are in your head, a lot of design arguments resolve themselves before anybody draws a box.&lt;/p&gt;</description></item><item><title>The C10K problem</title><link>https://7nolikov.dev/notes/c10k-problem/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/c10k-problem/</guid><description>&lt;p&gt;Dan Kegel&amp;rsquo;s 1999 write-up of why a server could not handle ten thousand simultaneous connections, and what would have to change.&lt;/p&gt;
&lt;p&gt;It is a historical document now - ten thousand connections is unremarkable - but it is the clearest explanation of &lt;em&gt;why&lt;/em&gt; every modern runtime is built the way it is. Thread-per-connection does not scale because threads cost memory and context switches. That single constraint produced epoll, kqueue, async I/O, event loops, and eventually goroutines and virtual threads.&lt;/p&gt;</description></item><item><title>TIGER_STYLE - TigerBeetle's engineering doc</title><link>https://7nolikov.dev/notes/tiger-style/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/tiger-style/</guid><description>&lt;p&gt;The engineering style guide from TigerBeetle, a distributed financial database. It is not really a style guide - it&amp;rsquo;s a document about how to build software that must not lose data.&lt;/p&gt;
&lt;p&gt;Things in it I keep coming back to: assert everything, at every layer, in production too. Allocate all memory up front so you can&amp;rsquo;t fail at the worst moment. Set an explicit limit on every loop and every queue, because &amp;ldquo;unbounded&amp;rdquo; is a bug waiting for load. Design so a failure is loud rather than silent.&lt;/p&gt;</description></item><item><title>Uncloud - Compose for production</title><link>https://7nolikov.dev/notes/uncloud/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/uncloud/</guid><description>&lt;p&gt;Fills the gap between &amp;ldquo;docker compose on a VPS&amp;rdquo; and Kubernetes. Clustering, automatic HTTPS, service discovery, a WireGuard mesh between machines - without a control plane.&lt;/p&gt;
&lt;p&gt;The design choice I find interesting: there is no central control plane at all. Every machine holds the full cluster state in a CRDT-backed distributed SQLite, syncing peer to peer. No etcd, no leader election, and the cluster keeps working when machines go offline.&lt;/p&gt;</description></item><item><title>No YAML</title><link>https://7nolikov.dev/notes/no-yaml/</link><pubDate>Mon, 19 May 2025 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/no-yaml/</guid><description>&lt;p&gt;The website noyaml.com humorously critiques the use of YAML in DevOps, particularly with Kubernetes. It highlights YAML&amp;rsquo;s lack of error handling, potential security vulnerabilities, and quirks (like misinterpreting &amp;ldquo;NO&amp;rdquo; as a boolean). Despite these issues, the site sarcastically acknowledges YAML&amp;rsquo;s widespread adoption, especially by Kubernetes, and its superiority to older configuration formats.&lt;/p&gt;
&lt;p&gt;See it on &lt;a href="https://noyaml.com/"&gt;noyaml.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See also:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://7nolikov.dev/notes/kubernetes-failure-stories/" class="backlink"&gt;Kubernetes Failure Stories&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Go Templates injection solved</title><link>https://7nolikov.dev/notes/go-templates-injection/</link><pubDate>Fri, 09 May 2025 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/go-templates-injection/</guid><description>&lt;p&gt;I personally encountered a Go templates injection problem in a project I was working on.&lt;/p&gt;
&lt;p&gt;Short version of the fix: use &lt;code&gt;html/template&lt;/code&gt;, never &lt;code&gt;text/template&lt;/code&gt;, for anything that reaches a browser. They have identical APIs, which is exactly the trap - the code compiles either way. &lt;code&gt;html/template&lt;/code&gt; escapes values based on where they land, so a value inside an attribute, inside a script tag and inside plain text all get escaped differently.&lt;/p&gt;</description></item><item><title>Software Architecture Premier</title><link>https://7nolikov.dev/notes/software-architecture-premier/</link><pubDate>Thu, 08 May 2025 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/software-architecture-premier/</guid><description>&lt;p&gt;A reference collection on software architecture: patterns, microservices, DDD, how to document architecture, and how to enforce architectural rules in a build.&lt;/p&gt;
&lt;p&gt;The last one is the part I find most useful - most architecture material stops at describing patterns, this one gets to keeping them true after the diagram is drawn. Reference implementations are Spring Boot.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/sivaprasadreddy/software-architecture-premier"&gt;github.com/sivaprasadreddy/software-architecture-premier&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;See also:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://7nolikov.dev/notes/system-design-primer/" class="backlink"&gt;System Design Primer&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://7nolikov.dev/notes/madr-architecture-decision-records/" class="backlink"&gt;MADR - architecture decision records&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>JSON API - RESTful API Specification</title><link>https://7nolikov.dev/notes/json-api/</link><pubDate>Sat, 04 Jan 2025 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/json-api/</guid><description>&lt;p&gt;A specification for what a JSON API response should look like, so you stop re-deciding it on every project.&lt;/p&gt;
&lt;p&gt;It settles the boring arguments - where errors go, how pagination and filtering are expressed, how related resources are included. Sparse fieldsets and compound documents are the two features that earn it: the client asks for exactly the fields it needs, and pulls related objects in one round trip instead of five.&lt;/p&gt;</description></item><item><title>HAL - Hypertext Application Language</title><link>https://7nolikov.dev/notes/hal/</link><pubDate>Fri, 03 Jan 2025 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/hal/</guid><description>&lt;p&gt;A tiny convention for putting links inside JSON API responses, so clients navigate instead of building URLs by hand.&lt;/p&gt;
&lt;figure class="codeblock not-prose relative scroll-mt-8" id="codeblock-01"&gt;
 &lt;aside
 class="absolute right-0 top-0 hidden rounded-bl-sm rounded-tr-sm bg-white/10 px-2 py-1 text-white/70 transition-opacity md:inline-block"
 &gt;
 &lt;div class="codeblock-meta flex max-w-xs flex-row items-center space-x-3"&gt;
 &lt;div class="small-caps shrink cursor-default truncate font-mono text-xs" aria-hidden="true"&gt;
 &lt;span class="relative"&gt;json&lt;/span&gt;
 &lt;/div&gt;
 &lt;div&gt;
 &lt;clipboard-copy
 type="button"
 aria-label="Copy code to clipboard"
 title="Copy code to clipboard"
 class="block cursor-pointer transition-colors hover:text-sky-400"
 target="#codeblock-01 code"
 &gt;
 &lt;svg
 xmlns="http://www.w3.org/2000/svg"
 fill="none"
 stroke="currentColor"
 stroke-width="2"
 stroke-linecap="round"
 stroke-linejoin="round"
 class="lucide lucide-clipboard h-4 w-4"
 viewBox="0 0 24 24"
&gt;
 &lt;rect width="8" height="4" x="8" y="2" rx="1" ry="1" /&gt;
 &lt;path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2" /&gt;
&lt;/svg&gt;

 &lt;/clipboard-copy&gt;
 &lt;/div&gt;
 &lt;div&gt;
 &lt;a
 href="#codeblock-01"
 class="block"
 aria-label="Link to this code block"
 title="Link to this code block"
 &gt;
 &lt;svg
 xmlns="http://www.w3.org/2000/svg"
 width="16"
 height="16"
 fill="none"
 stroke="currentColor"
 stroke-linecap="round"
 stroke-linejoin="round"
 stroke-width="2"
 class="lucide lucide-link w-4 h-4 block"
 viewBox="0 0 24 24"
&gt;
 &lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" /&gt;
 &lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" /&gt;
&lt;/svg&gt;

 &lt;/a&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 &lt;/aside&gt;
 &lt;p class="sr-only"&gt;json code snippet start&lt;/p&gt;</description></item><item><title>Calendly - Easy scheduling tool</title><link>https://7nolikov.dev/notes/calendly/</link><pubDate>Thu, 02 Jan 2025 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/calendly/</guid><description>&lt;p&gt;Share a link, people book a slot from your free time, both sides get a calendar invite.&lt;/p&gt;
&lt;p&gt;It syncs with Google and Outlook so you don&amp;rsquo;t get double-booked, and it handles time zones - which is the actual reason to use it if the people you talk to live somewhere else.&lt;/p&gt;
&lt;p&gt;Kills the &amp;ldquo;does Tuesday work for you?&amp;rdquo; email thread, which is worth more than it sounds.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://calendly.com/"&gt;calendly.com&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Open resume parser</title><link>https://7nolikov.dev/notes/open-resume-parser/</link><pubDate>Wed, 01 Jan 2025 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/open-resume-parser/</guid><description>&lt;p&gt;Check if your resume is ATS-friendly for free - Open-Resume&amp;rsquo;s parser analyzes your resume to ensure it can be easily read by Applicant Tracking Systems, boosting your chances of landing interviews.&lt;/p&gt;
&lt;p&gt;See it on github: &lt;a href="https://github.com/xitanggg/open-resume"&gt;https://github.com/xitanggg/open-resume&lt;/a&gt;&lt;/p&gt;</description></item><item><title>PostHog</title><link>https://7nolikov.dev/notes/posthog/</link><pubDate>Tue, 31 Dec 2024 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/posthog/</guid><description>&lt;p&gt;Open-source product analytics: events, funnels, session replay and feature flags in one place, self-hostable if you want the data on your own servers.&lt;/p&gt;
&lt;p&gt;The reason I picked it over the alternatives is not the feature list. It has a permanent free allowance and a &lt;strong&gt;hard $0 billing cap&lt;/strong&gt; - not &amp;ldquo;generous limits&amp;rdquo;, an actual cap you can set. For a side project, that is the difference between analytics and a surprise invoice.&lt;/p&gt;</description></item><item><title>Book - Going Offline</title><link>https://7nolikov.dev/notes/going-offline-book/</link><pubDate>Thu, 26 Dec 2024 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/going-offline-book/</guid><description>&lt;p&gt;Jeremy Keith&amp;rsquo;s book on service workers and making a site work without a connection.&lt;/p&gt;
&lt;p&gt;It is short and it is the clearest explanation of service workers I&amp;rsquo;ve come across. The core idea: a service worker is a script sitting between your page and the network, and once you accept that, caching strategies stop being magic - you decide per request whether to try the network first, the cache first, or race them.&lt;/p&gt;</description></item><item><title>Spring Modulith 1.3</title><link>https://7nolikov.dev/notes/spring-modulith/</link><pubDate>Mon, 23 Dec 2024 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/spring-modulith/</guid><description>&lt;p&gt;Microservices -&amp;gt; modulith: the trend became real.&lt;/p&gt;
&lt;p&gt;Spring Modulith supports modular monoliths - clear boundaries between modules, verified at build time, all running in one process. You get the enforced separation that pushed people to microservices, without the network between the parts.&lt;/p&gt;
&lt;p&gt;Module boundaries are checked by tests, so a violation fails the build instead of being noticed a year later. If you ever need to split a module into a service, the seam is already there.&lt;/p&gt;</description></item><item><title>The Password Game</title><link>https://7nolikov.dev/notes/password-game/</link><pubDate>Sun, 22 Dec 2024 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/password-game/</guid><description>&lt;p&gt;The password game has rules that ensure I will never see the congratulations screen. Good luck!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://neal.fun/password-game/"&gt;Link to the game&lt;/a&gt;&lt;/p&gt;</description></item><item><title>B-Trees and database indexes</title><link>https://7nolikov.dev/notes/b-trees-and-database-indexes/</link><pubDate>Sat, 21 Dec 2024 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/b-trees-and-database-indexes/</guid><description>&lt;p&gt;PlanetScale on why database indexes are B-trees and not something simpler.&lt;/p&gt;
&lt;p&gt;The part worth keeping: a B-tree keeps keys sorted and balanced, so a lookup costs a handful of disk reads instead of a full scan. Range queries - everything between two values - come almost free, because the keys already sit in order next to each other.&lt;/p&gt;
&lt;p&gt;That last property is why &lt;code&gt;WHERE id BETWEEN 100 AND 200&lt;/code&gt; is cheap on an indexed column, and why a hash index would not help you there at all.&lt;/p&gt;</description></item><item><title>Delta Lake vs Apache Iceberg</title><link>https://7nolikov.dev/notes/delta-lake-vs-apache-iceberg/</link><pubDate>Fri, 20 Dec 2024 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/delta-lake-vs-apache-iceberg/</guid><description>&lt;p&gt;Two table formats that sit on top of files in object storage and give you ACID transactions, schema evolution and time travel - the things a pile of Parquet files does not have on its own.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Delta Lake&lt;/strong&gt; came out of Databricks and is deepest there and in Spark.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Iceberg&lt;/strong&gt; is engine-agnostic by design and runs under Spark, Flink, Trino and more. Its hidden partitioning is the feature to know: you partition by a column, and readers don&amp;rsquo;t have to know the partition scheme to hit it. With traditional partitioning, a query that doesn&amp;rsquo;t mention the partition column scans everything.&lt;/p&gt;</description></item><item><title>Maven archetypes</title><link>https://7nolikov.dev/notes/maven-archetypes/</link><pubDate>Sat, 14 Dec 2024 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/maven-archetypes/</guid><description>&lt;p&gt;Maven archetypes are templates that help developers quickly set up a new project with a predefined structure, files, and code for a specific type of application.
It&amp;rsquo;s extremely useful for livecoding interviews when you need to quickly create a project skeleton.&lt;/p&gt;</description></item><item><title>New MS Office to .MD converter</title><link>https://7nolikov.dev/notes/doc-markdown-converter/</link><pubDate>Sat, 14 Dec 2024 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/doc-markdown-converter/</guid><description>&lt;p&gt;&lt;strong&gt;MarkItDown&lt;/strong&gt; from Microsoft converts &lt;code&gt;.docx&lt;/code&gt;, &lt;code&gt;.xlsx&lt;/code&gt;, &lt;code&gt;.pptx&lt;/code&gt; and PDFs into Markdown.&lt;/p&gt;
&lt;p&gt;Useful for two things: getting documents out of Office and into a repo or a notes vault, and feeding documents to an LLM, which handles Markdown far better than a binary blob.&lt;/p&gt;
&lt;p&gt;Google Docs can also export Markdown directly now, if that&amp;rsquo;s where your documents live.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/microsoft/markitdown"&gt;github.com/microsoft/markitdown&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Modern Make</title><link>https://7nolikov.dev/notes/modern-make/</link><pubDate>Thu, 12 Dec 2024 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/modern-make/</guid><description>&lt;p&gt;A short, clean reference for Makefile syntax - targets, dependencies, rules, and the parts that trip everybody up.&lt;/p&gt;
&lt;p&gt;Good for a refresher when you have not touched Make in a while and cannot remember whether it is &lt;code&gt;$@&lt;/code&gt; or &lt;code&gt;$&amp;lt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://makefile.site/"&gt;makefile.site&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;See also:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://7nolikov.dev/notes/cli-guidelines/" class="backlink"&gt;Command Line Interface Guidelines&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Learn git branching</title><link>https://7nolikov.dev/notes/learn-git-branching/</link><pubDate>Wed, 11 Dec 2024 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/learn-git-branching/</guid><description>&lt;p&gt;Understanding Git branching has mattered a lot in my career, and it is genuinely hard to picture what a rebase does to a commit graph from the command line alone.&lt;/p&gt;
&lt;p&gt;This solves that. Interactive exercises with a live diagram of the commit tree - you run a real command, you watch the branches move.&lt;/p&gt;
&lt;p&gt;It covers rebasing, cherry-picking, detached HEAD and remote tracking, which are exactly the parts people fake their way through. And you can undo anything, so there is nothing to be afraid of breaking.&lt;/p&gt;</description></item><item><title>REST API Tutorial</title><link>https://7nolikov.dev/notes/rest-api-tutorial/</link><pubDate>Tue, 10 Dec 2024 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/rest-api-tutorial/</guid><description>&lt;p&gt;A reference site for REST - resources, HTTP methods, status codes, and what statelessness actually requires of you.&lt;/p&gt;
&lt;p&gt;Useful as the thing you send someone who is about to design an API, or to check yourself on which status code is correct before you invent one.&lt;/p&gt;
&lt;p&gt;Its section on Richardson&amp;rsquo;s maturity model is the part most people have never read, and it explains why almost nothing anyone calls REST is actually REST.&lt;/p&gt;</description></item><item><title>EdgeDB - Turbocharged Postgres</title><link>https://7nolikov.dev/notes/edge-db/</link><pubDate>Mon, 09 Dec 2024 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/edge-db/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Updated: EdgeDB was renamed to &lt;strong&gt;Gel&lt;/strong&gt; in February 2025, and it now also speaks plain Postgres SQL. This note predates that - the link goes to the new site.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Postgres underneath, a different data model and query language on top.&lt;/p&gt;
&lt;p&gt;You declare a schema with types and links between them, then query with EdgeQL, which returns nested objects instead of joined rows. Fetching an order with its customer and line items is one query and one shaped result, not a join you reassemble in application code.&lt;/p&gt;</description></item><item><title>RevealJS - HTML Presentation Framework</title><link>https://7nolikov.dev/notes/revealjs/</link><pubDate>Thu, 05 Dec 2024 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/revealjs/</guid><description>&lt;p&gt;Presentations written in HTML or Markdown, rendered in a browser.&lt;/p&gt;
&lt;p&gt;Slides live in a text file, which means they diff, review and version like code. Speaker notes, PDF export, and it scales to a phone screen.&lt;/p&gt;
&lt;p&gt;If you keep your slides in a repo next to the thing you are presenting, this is the tool. Host it on GitHub Pages for free.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://revealjs.com/demo/?view=scroll"&gt;Demo&lt;/a&gt; · &lt;a href="https://revealjs.com/"&gt;revealjs.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;See also:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://7nolikov.dev/notes/going-offline-book/" class="backlink"&gt;Book - Going Offline&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>PostgreSQL Exercises</title><link>https://7nolikov.dev/notes/postgresql-exercises/</link><pubDate>Mon, 02 Dec 2024 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/postgresql-exercises/</guid><description>&lt;p&gt;Practice SQL against a real sample database in the browser. Free, no registration, and it checks your answer.&lt;/p&gt;
&lt;p&gt;It goes from basic &lt;code&gt;SELECT&lt;/code&gt; all the way to window functions and recursive CTEs, which is the part most people skip and then meet in an interview. Extremely helpful for interview prep, or for getting SQL back after a year of writing application code.&lt;/p&gt;
&lt;p&gt;Big thanks to &lt;a href="https://alisdairowens.net/"&gt;Alisdair Owens&lt;/a&gt; for creating and maintaining this fantastic resource!&lt;/p&gt;</description></item><item><title>Conventional commits</title><link>https://7nolikov.dev/notes/conventional-commits/</link><pubDate>Sun, 01 Dec 2024 00:00:00 +0000</pubDate><author>7nolikov@gmail.com (Dmitrii Novikov)</author><guid>https://7nolikov.dev/notes/conventional-commits/</guid><description>&lt;p&gt;Thousands of times in my professional career I have figured out the reason for changes in the history of the Git. And here is the solution to the problem!&lt;/p&gt;
&lt;figure class="codeblock not-prose relative scroll-mt-8" id="codeblock-01"&gt;
 &lt;aside
 class="absolute right-0 top-0 hidden rounded-bl-sm rounded-tr-sm bg-white/10 px-2 py-1 text-white/70 transition-opacity md:inline-block"
 &gt;
 &lt;div class="codeblock-meta flex max-w-xs flex-row items-center space-x-3"&gt;
 &lt;div class="small-caps shrink cursor-default truncate font-mono text-xs" aria-hidden="true"&gt;
 &lt;span class="relative"&gt;&lt;/span&gt;
 &lt;/div&gt;
 &lt;div&gt;
 &lt;clipboard-copy
 type="button"
 aria-label="Copy code to clipboard"
 title="Copy code to clipboard"
 class="block cursor-pointer transition-colors hover:text-sky-400"
 target="#codeblock-01 code"
 &gt;
 &lt;svg
 xmlns="http://www.w3.org/2000/svg"
 fill="none"
 stroke="currentColor"
 stroke-width="2"
 stroke-linecap="round"
 stroke-linejoin="round"
 class="lucide lucide-clipboard h-4 w-4"
 viewBox="0 0 24 24"
&gt;
 &lt;rect width="8" height="4" x="8" y="2" rx="1" ry="1" /&gt;
 &lt;path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2" /&gt;
&lt;/svg&gt;

 &lt;/clipboard-copy&gt;
 &lt;/div&gt;
 &lt;div&gt;
 &lt;a
 href="#codeblock-01"
 class="block"
 aria-label="Link to this code block"
 title="Link to this code block"
 &gt;
 &lt;svg
 xmlns="http://www.w3.org/2000/svg"
 width="16"
 height="16"
 fill="none"
 stroke="currentColor"
 stroke-linecap="round"
 stroke-linejoin="round"
 stroke-width="2"
 class="lucide lucide-link w-4 h-4 block"
 viewBox="0 0 24 24"
&gt;
 &lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" /&gt;
 &lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" /&gt;
&lt;/svg&gt;

 &lt;/a&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 &lt;/aside&gt;
 &lt;p class="sr-only"&gt; code snippet start&lt;/p&gt;</description></item></channel></rss>