<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Atoms - dzx.cz</title>
    <link>https://dzx.cz/atoms/</link>
    <description>Atoms - dzx.cz</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-US</language>
    <managingEditor>matousdzivjak@gmail.com (Matouš Dzivjak)</managingEditor>
    <webMaster>matousdzivjak@gmail.com (Matouš Dzivjak)</webMaster>
    <copyright>This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.</copyright>
    <lastBuildDate>Sun, 22 Feb 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://dzx.cz/atoms/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Gopls MCP</title>
      <link>https://dzx.cz/2026-02-22/gopls-mcp/</link>
      <pubDate>Sun, 22 Feb 2026 00:00:00 +0000</pubDate>
      <author>matousdzivjak@gmail.com (Matouš Dzivjak)</author>
      <guid>https://dzx.cz/2026-02-22/gopls-mcp/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://go.dev/gopls/&#34;&gt;Gopls&lt;/a&gt;, the language server for Go, now comes with a built-in &lt;a href=&#34;https://modelcontextprotocol.io/docs/getting-started/intro&#34;&gt;MCP&lt;/a&gt; support&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;. MCPs are all the rage and here the excitement is warranted by an actual use-case. The gopls MCP provides multiple tools that make LLMs efficient when working in Go codebases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;go_workspace&lt;/code&gt; to understand the overall structure of the workspace&lt;/li&gt;
&lt;li&gt;&lt;code&gt;go_search&lt;/code&gt; for looking for a specific type, function, or variable&lt;/li&gt;
&lt;li&gt;&lt;code&gt;go_file_context&lt;/code&gt; that returns contents of a file and how it connects to other files &lt;em&gt;in the same package&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;go_package_api&lt;/code&gt; to understand package&amp;rsquo;s public API, even for third-part dependencies&lt;/li&gt;
&lt;li&gt;&lt;code&gt;go_symbol_references&lt;/code&gt; for finding all references to an identifier&lt;/li&gt;
&lt;li&gt;&lt;code&gt;go_diagnostics&lt;/code&gt; that reports any build or analysis errors&lt;/li&gt;
&lt;li&gt;&lt;code&gt;go_vulncheck&lt;/code&gt; which runs vulnerability scan over dependencies and returns any findings&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To instruct LLMs to use these tools, there are built-in instructions under &lt;code&gt;gopls mcp -instructions&lt;/code&gt;. I have tried relying on the MCP without &lt;em&gt;explicit&lt;/em&gt; instructions in which case the tools seemed mostly ignored. The fix for that is to either manually paste the instructions into the context, or use either &lt;a href=&#34;https://agents.md/&#34;&gt;AGENTS.md&lt;/a&gt; or &lt;a href=&#34;https://agentskills.io/home&#34;&gt;Agent Skills&lt;/a&gt;, both nowadays supported by majority of LLM tools.&lt;/p&gt;
&lt;p&gt;The installation of Gopls MCP varies by tool but for codex it is as simple as:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;codex mcp add gopls gopls mcp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;or by manually adding it to your configuration under &lt;code&gt;~/.codex/config.toml&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp_servers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;gopls&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;command&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;gopls&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;args&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;mcp&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And if you are afraid of the instructions getting outdated, I found this to work well:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-md&#34; data-lang=&#34;md&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;**IMPORTANT**: Before working with Go code run &lt;span class=&#34;sb&#34;&gt;`gopls mcp -instructions`&lt;/span&gt; to read Go-specific instructions.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://go.dev/gopls/features/mcp&#34;&gt;Gopls: Model Context Protocol support&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Rust on ESP32</title>
      <link>https://dzx.cz/2025-05-08/rust-on-esp32/</link>
      <pubDate>Thu, 08 May 2025 00:00:00 +0000</pubDate>
      <author>matousdzivjak@gmail.com (Matouš Dzivjak)</author>
      <guid>https://dzx.cz/2025-05-08/rust-on-esp32/</guid>
      <description>&lt;p&gt;I have been tinkering with &lt;a href=&#34;https://www.quickspot.io/index.html&#34;&gt;Walter&lt;/a&gt; - an ESP32-S3 module with NB-IoT, LTE-M, and GPS last week. Going the hard route a writing in Rust instead of using the &lt;a href=&#34;https://github.com/QuickSpot&#34;&gt;provided libraries&lt;/a&gt; for C++ and &lt;a href=&#34;https://micropython.org/&#34;&gt;MicroPython&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To my understanding, there are multiple paths to take. Using the standard library (&lt;code&gt;std&lt;/code&gt;) one can build on top of &lt;a href=&#34;https://github.com/espressif/esp-idf&#34;&gt;ESP-IDF&lt;/a&gt; (IoT Development Framework), a C-based development framework. This is the heavier, &lt;em&gt;batteries included&lt;/em&gt;, approach where drivers for WiFi, networking, HTTP, MQTT, peripherals and more are all provided by the underlying system based on &lt;a href=&#34;https://www.freertos.org/&#34;&gt;FreeRTOS&lt;/a&gt;. The alternative is &lt;code&gt;no_std&lt;/code&gt;. This requires writing everything from scratch (or at least using the right libraries) but gives full control of memory, timing, and peripherals.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://embassy.dev/&#34;&gt;Embassy&lt;/a&gt; makes the &lt;code&gt;no_std&lt;/code&gt; path easier. It&amp;rsquo;s a framework that allows using &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; for efficient multi-tasking, bridging the gap between &lt;em&gt;write everything yourself&lt;/em&gt; and full blown-out &lt;a href=&#34;https://en.wikipedia.org/wiki/Real-time_operating_system&#34;&gt;RTOS&lt;/a&gt;. Embassy takes care of scheduling, interrupts, and making sure the CPU sleeps when there&amp;rsquo;s nothing to do. Embassy itself doesn&amp;rsquo;t know anything about the underlying hardware, that&amp;rsquo;s where &lt;a href=&#34;https://github.com/esp-rs/esp-hal/tree/main/esp-hal-embassy&#34;&gt;esp-hal-embassy&lt;/a&gt; comes in as a glue between the hardware abstraction layer and the Embassy framework, providing async-aware drivers for ESP hardware and timers and interrupts to drive the async task system.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>SumUp Agent Toolkit</title>
      <link>https://dzx.cz/2025-04-11/sumup-agent-toolkit/</link>
      <pubDate>Fri, 11 Apr 2025 00:00:00 +0000</pubDate>
      <author>matousdzivjak@gmail.com (Matouš Dzivjak)</author>
      <guid>https://dzx.cz/2025-04-11/sumup-agent-toolkit/</guid>
      <description>&lt;p&gt;Every second Friday at SumUp it&amp;rsquo;s a Hackday - a day to spend on learning, side-projects, and hacking. For me this usually meant working on our SDKs and developer portal. &lt;a href=&#34;https://github.com/sumup/sumup-agent-toolkit/&#34;&gt;SumUp Agent Toolkit&lt;/a&gt; is the latest addition, an SDK for agentic workflows build on top of our &lt;a href=&#34;https://github.com/sumup/sumup-ts&#34;&gt;Typescript SDK&lt;/a&gt;. It supports &lt;a href=&#34;https://www.langchain.com/&#34;&gt;LangChain&lt;/a&gt;, &lt;a href=&#34;https://sdk.vercel.ai/&#34;&gt;AI SDK&lt;/a&gt;, and &lt;a href=&#34;https://github.com/openai/openai-node&#34;&gt;OpenAI&lt;/a&gt; as well as &lt;a href=&#34;https://modelcontextprotocol.io/introduction&#34;&gt;Model Context Protocol&lt;/a&gt; which is all the rage at the moment.&lt;/p&gt;
&lt;p&gt;It was fun to build, the most complicated part was to figure out types for the shared module with tool definitions, where after some back and forth this seemed to do the trick:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ts&#34; data-lang=&#34;ts&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;SumUp&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;@sumup/sdk&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;z&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;zod&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;ZodObjectAny&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ZodObject&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Tool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;Args&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;extends&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;ZodObjectAny &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;ZodObjectAny&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;description&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;parameters&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;Args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;callback&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;sumup&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;SumUp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;args&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;z.output&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;Args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Promise&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I have then built a tiny CLI tool that takes our OpenAPI specs and generates parameter types and tools for every single publicly available endpoint. This part is extremely hacky (part of the reason why it isn&amp;rsquo;t included in the repository so far) but saves a lot of manual work and makes keeping the implementation up to date easier.&lt;/p&gt;
&lt;p&gt;It can automatically generate &lt;a href=&#34;https://zod.dev/&#34;&gt;zod&lt;/a&gt; types for all operations:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ts&#34; data-lang=&#34;ts&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;listMerchantMembersParameters&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;object&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;offset&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;z&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;number&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;describe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`Offset of the first member to return.`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;optional&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;limit&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;z&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;number&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;describe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`Maximum number of members to return.`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;optional&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;email&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;z&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;describe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`Filter the returned members by email address prefix.`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;optional&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;status&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;z&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;enum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;accepted&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;pending&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;expired&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;disabled&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;unknown&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;describe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`Filter the returned members by the membership status.`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;optional&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;roles&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;z&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;array&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;describe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`Filter the returned members by role.`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;optional&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;merchant_code&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;z.string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;describe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`Merchant code.`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;as well as tool definitions:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ts&#34; data-lang=&#34;ts&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;listMerchantMembers&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;Tool&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;list_merchant_members&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;description&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`Lists merchant members.`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;parameters&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;listMerchantMembersParameters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;callback&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;sumup&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;SumUp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;merchant_code&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;args&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;infer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;typeof&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;listMerchantMembersParameters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;res&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;sumup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;members&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;merchant_code&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;JSON&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;stringify&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s still cheaper, more secure, and more environmentally friendly to whip up a terminal and curl instead but at least it allowed us to test our Typescript SDK (and fix a few bugs). And given the current sentiment of the leadership, it might make it easier to sell the idea of a dedicated team for public APIs and developer experience.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Go SDK generator</title>
      <link>https://dzx.cz/2025-01-08/go-sdk-generator/</link>
      <pubDate>Wed, 08 Jan 2025 00:00:00 +0000</pubDate>
      <author>matousdzivjak@gmail.com (Matouš Dzivjak)</author>
      <guid>https://dzx.cz/2025-01-08/go-sdk-generator/</guid>
      <description>&lt;p&gt;Tiny, work-related, long overdue project is finally shaping up - SumUp finally has a working &lt;a href=&#34;https://github.com/sumup/sumup-go&#34;&gt;Go SDK&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s surprising void of a solid OpenAPI tooling for Go, &lt;a href=&#34;https://github.com/deepmap/oapi-codegen&#34;&gt;oapi-codegen&lt;/a&gt; being the go-to best option yet somehow unfit for SDKs. oapi-codegen focuses on supporting everything one might describe in OpenAPI specs at the cost of ergonomic and structured code that requires opinionated approach. And given SDKs are becoming the norm of a first-class developer tooling, we decided to roll with our own generator. For now, you can check the generated code in &lt;a href=&#34;https://github.com/sumup/sumup-go&#34;&gt;sumup-go&lt;/a&gt; but I hope we can open source our tool within the following month, giving a little back to the open source community that we are taking plenty from.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Keeping packages up to date</title>
      <link>https://dzx.cz/2024-12-11/keeping-packages-up-to-date/</link>
      <pubDate>Wed, 11 Dec 2024 00:00:00 +0000</pubDate>
      <author>matousdzivjak@gmail.com (Matouš Dzivjak)</author>
      <guid>https://dzx.cz/2024-12-11/keeping-packages-up-to-date/</guid>
      <description>&lt;p&gt;&lt;code&gt;brew upgrade&lt;/code&gt; is a convenient way to update your packages to their latest version. The issue is, at one point or another not all your packages will be installed by &lt;code&gt;brew&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To keep my system up to date I am using a tiny &lt;a href=&#34;https://fishshell.com/&#34;&gt;fish&lt;/a&gt; function that updates binaries installed through my most commonly used package managers, tools, and languages:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fish&#34; data-lang=&#34;fish&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;update&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;--description&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Update binaries&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;brew&lt;/span&gt; update&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;brew&lt;/span&gt; upgrade
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;fisher&lt;/span&gt; update
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;gup&lt;/span&gt; update
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;npm&lt;/span&gt; update &lt;span class=&#34;na&#34;&gt;-g&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;rustup&lt;/span&gt; update
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;cargo&lt;/span&gt; install-update &lt;span class=&#34;na&#34;&gt;-a&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Every now and then, I run &lt;code&gt;update&lt;/code&gt; and get my whole system to latest version of tools. I tried &lt;a href=&#34;https://github.com/topgrade-rs/topgrade&#34;&gt;topgrade&lt;/a&gt; before, but it&amp;rsquo;s heavyweight for my use case and often failed for (to me) unclear reasons. On the other hand, &lt;code&gt;update&lt;/code&gt; function is less than 10 lines of code long and allows me to easily find the commands that run under the hood in case anything fails.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Reading the Azerothcore codebase</title>
      <link>https://dzx.cz/2024-12-02/reading-the-azerothcore-codebase/</link>
      <pubDate>Mon, 02 Dec 2024 00:00:00 +0000</pubDate>
      <author>matousdzivjak@gmail.com (Matouš Dzivjak)</author>
      <guid>https://dzx.cz/2024-12-02/reading-the-azerothcore-codebase/</guid>
      <description>&lt;p&gt;Whiles on sabbatical in New Zealand I have been reading on game development and nostalgically remembering the years I have spent playing video games for the majority of my free time. The fondest memories I have are of World of Warcraft and the endless hours of leveling, raiding, and completing daily quests. Now I am completing the journey from the other side couple of years later, reading through the code base of &lt;a href=&#34;https://github.com/azerothcore/azerothcore-wotlk&#34;&gt;Azerothcore&lt;/a&gt;, an open-source WoW server for the &lt;a href=&#34;https://en.wikipedia.org/wiki/World_of_Warcraft:_Wrath_of_the_Lich_King&#34;&gt;Wrath of the Lich King&lt;/a&gt;  expansion which is at this point 16 years old.&lt;/p&gt;
&lt;p&gt;Getting a glimpse of the machinery behind one of the greatest MMOs of all time is a surprisingly fun endeavor. The code base is exceptionally well organized and easy to navigate even as a complete novice. For example, many of the game entities are defined as standalone &lt;a href=&#34;https://github.com/azerothcore/azerothcore-wotlk/tree/master/src/server/scripts&#34;&gt;scripts&lt;/a&gt; that define hooks for the main event loop which leaves the core classes clean while providing necessary customization for a rich game world.&lt;/p&gt;
&lt;p&gt;I have no takeaway to wrap this up with except that writing game servers after all, doesn&amp;rsquo;t seem that different from building large monolithic APIs. Clear naming and good abstractions go a long way.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Pictures from New Zealand</title>
      <link>https://dzx.cz/2024-11-23/pictures-from-new-zealand/</link>
      <pubDate>Sat, 23 Nov 2024 00:00:00 +0000</pubDate>
      <author>matousdzivjak@gmail.com (Matouš Dzivjak)</author>
      <guid>https://dzx.cz/2024-11-23/pictures-from-new-zealand/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Look to my coming at first light on the 5th day. At dawn, look to the East.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Peter Jackson&amp;rsquo;s pick of New Zealand as the filming location of the original trilogy of Lord of the Rings was a rightful pick even if it wasn&amp;rsquo;t his homeland. New Zealand&amp;rsquo;s nature is majestic in every aspect and the only thing I was missings was Howard Shore&amp;rsquo;s &lt;em&gt;The Ride of the Rohirrim&lt;/em&gt; queuing in whenever I entered a coffee shop.&lt;/p&gt;
&lt;p&gt;Verify my claim in the &lt;a href=&#34;https://dzx.cz/photos/&#34;&gt;Photos&lt;/a&gt; section.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Photos</title>
      <link>https://dzx.cz/2024-06-09/photos/</link>
      <pubDate>Sun, 09 Jun 2024 00:00:00 +0000</pubDate>
      <author>matousdzivjak@gmail.com (Matouš Dzivjak)</author>
      <guid>https://dzx.cz/2024-06-09/photos/</guid>
      <description>&lt;p&gt;I added a &lt;a href=&#34;https://dzx.cz/photos/&#34;&gt;Photos&lt;/a&gt; section to the website, intending to make it a curated gallery of all the photos I keep collecting and sporadically sharing on Insagram, arguably one of the worst platforms for actually sharing photography.&lt;/p&gt;
&lt;p&gt;Initially, I wanted to leverage the same setup I already use for other images on this website - &lt;a href=&#34;https://git-lfs.com/&#34;&gt;Git LFS&lt;/a&gt;. This proved to be problematic though, as fetching the repository results in all pictures being downloaded as well. Furthermore, GitHub restricts the LFS space to 2 GB for free accounts which I am afraid of hitting quite early.&lt;/p&gt;
&lt;p&gt;After some research I opted for storing all the photos in S3 (&lt;a href=&#34;https://www.cloudflare.com/developer-platform/r2/&#34;&gt;CloudFlare R2&lt;/a&gt; to be precise) under my own domain. The process of adding a picture has a few steps:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pick a picture and a name&lt;/strong&gt;. Picking a name proved to be harder than I expected, I would like a consistent naming schemantics but&amp;hellip; what? I tried to use location names but my camera doesn&amp;rsquo;t add the longitude and latitude to picture unless it is connected to my phone, which it rarely is, and figuring out the locations manually is a tedious manual task.&lt;/p&gt;
&lt;p&gt;Activity/subject of the photo seemed like a good approach but I need to generate unique slugs for the file names. One could have an incrementing counter (e.g. &lt;code&gt;cycling_0005&lt;/code&gt;) the only issue being that I am not adding the photos in order; at least for now while backfilling.&lt;/p&gt;
&lt;p&gt;In the end I decided to give up on consistency for now and see if I find a better approach in the future.&lt;/p&gt;
&lt;p&gt;Next step is to &lt;strong&gt;resize and generate thumbnail&lt;/strong&gt;. This involves using &lt;a href=&#34;https://imagemagick.org/&#34;&gt;ImageMagick&lt;/a&gt; to generate 3 different sizes (512, 1024, and 2048 px) in 2 different formats (jpg and webp).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Upload images to R2&lt;/strong&gt; using &lt;a href=&#34;https://rclone.org/&#34;&gt;rclone&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Last but not least, I store the image metadata in &lt;a href=&#34;https://github.com/matoous/dzxcz&#34;&gt;matoous/dzxcz&lt;/a&gt; repository (source of this website). The metadata contain the image slug, the date the photo was taken, names of the original file and thumbprints, plus all available &lt;a href=&#34;https://en.wikipedia.org/wiki/Exif&#34;&gt;EXIF&lt;/a&gt; metadata as stored by the camera, e.g.:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nn&#34;&gt;---&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Rocks (Bosnia)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;date&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2023-10-02 12:53:27&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;iso&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;200&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;focal_length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;26&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;f_number&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;5.6&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;ev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;exposure&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;1/500&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;RICOH GR IIIx&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;make&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;RICOH IMAGING COMPANY, LTD.&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;srcset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;jpg512&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;rocks_bosnia_512.jpg&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;jpg1024&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;rocks_bosnia_1024.jpg&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;jpg2048&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;rocks_bosnia_2048.jpg&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;webp512&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;rocks_bosnia_512.webp&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;webp1024&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;rocks_bosnia_1024.webp&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;webp2048&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;rocks_bosnia_2048.webp&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;original&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;rocks_bosnia.jpg&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nn&#34;&gt;---&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To make all of this easier I wrote a little &lt;a href=&#34;https://github.com/matoous/dzxcz/tree/main/cli&#34;&gt;CLI tool&lt;/a&gt; that wraps all of these steps under 1 command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;dzx --name &lt;span class=&#34;s2&#34;&gt;&amp;#34;Valencia 2023 - Sunset (Spain)&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/Volumes/LaCie 01/2023-12 Valencia/Edited/R0001551.jpg&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;a href=&#34;https://dzx.cz/photos/&#34;&gt;Photos&lt;/a&gt; archive is displayed using &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout&#34;&gt;CSS grid&lt;/a&gt; with &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout/Masonry_layout&#34;&gt;Masonry layout&lt;/a&gt; that&amp;rsquo;s a new experimental feature in CSS, currently not supported by default by almost any browser. If you want to test it out and have the page display properly you should be able to enable masonry layout in your browser, in Firefox for example under &lt;code&gt;about:config&lt;/code&gt;, feature &lt;code&gt;layout.css.grid-template-masonry-value.enabled&lt;/code&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Typst</title>
      <link>https://dzx.cz/2024-05-04/typst/</link>
      <pubDate>Sat, 04 May 2024 00:00:00 +0000</pubDate>
      <author>matousdzivjak@gmail.com (Matouš Dzivjak)</author>
      <guid>https://dzx.cz/2024-05-04/typst/</guid>
      <description>&lt;p&gt;This weekend I have been updating and rewritting my CV, in &lt;a href=&#34;https://typst.app/&#34;&gt;Typst&lt;/a&gt;. The official description of Typst is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A new markup-based typesetting system that is powerful and easy to learn.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;which is true and maybe even an understatement. Typst is &lt;em&gt;easy&lt;/em&gt; to learn, so much so that after understanding a few basic principles, one can guess how the rest works (exaggering here, but the language is indeed neatly designed and structured). It&amp;rsquo;s a &lt;a href=&#34;https://en.wikipedia.org/wiki/LaTeX&#34;&gt;LaTeX&lt;/a&gt; for human beings. Typst support all the important things out of the box; tables, bibliography, figures, you name it. Furthermore, there&amp;rsquo;s the &lt;a href=&#34;https://typst.app/universe/search?kind=packages&#34;&gt;Typst Universe&lt;/a&gt; with evergrowing number of packages, to name a few, there&amp;rsquo;s a &lt;a href=&#34;https://typst.app/universe/package/charged-ieee&#34;&gt;IEEE-style paper template&lt;/a&gt;, &lt;a href=&#34;https://typst.app/universe/package/codly&#34;&gt;codly&lt;/a&gt; for code snippets, &lt;a href=&#34;https://typst.app/universe/package/drafting&#34;&gt;drafting&lt;/a&gt; for comments and margin notes and much more, all easily searchable.&lt;/p&gt;
&lt;p&gt;I wish Typst existing back during my university years. LaTeX was a love-hate relationship, especially when it comes to installing packages and running everything locally.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Race Nutrition</title>
      <link>https://dzx.cz/2024-05-03/race-nutrition/</link>
      <pubDate>Fri, 03 May 2024 00:00:00 +0000</pubDate>
      <author>matousdzivjak@gmail.com (Matouš Dzivjak)</author>
      <guid>https://dzx.cz/2024-05-03/race-nutrition/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://snowdonia.utmb.world/&#34;&gt;Ultra-trail Snowdonia&lt;/a&gt; is just behind the corner with less than 8 days to go. Learning from my past mistakes I&amp;rsquo;ve done a research on a race nutrition, documenting everything in the &lt;a href=&#34;https://wiki.dzx.cz/sports/running&#34;&gt;Wiki&lt;/a&gt;. The race nutrition approach boils down to the same best practices one would apply during training - do what you have tried and tested and what works for you. The same way you wouldn&amp;rsquo;t line up for a 100km race in a new shoes you don&amp;rsquo;t want to change your diet the week before the race. A few notes the summarize what I&amp;rsquo;ve learned:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Eat what you are used to and don&amp;rsquo;t change that too much before the race&lt;/li&gt;
&lt;li&gt;2-3 days before the start, cut out fiber. Fiber slows down digestion which is desired in regular regime but you don&amp;rsquo;t want to feel full during the race and what you eat needs to be absorbed fast.&lt;/li&gt;
&lt;li&gt;Avoid fats, while their are great source of energy they take a lot of time to process.&lt;/li&gt;
&lt;li&gt;The day before the race, don&amp;rsquo;t over-eat. You want to feel slightly hungry and start the race with relatively empty stomach.&lt;/li&gt;
&lt;li&gt;During the race, the rule of thumb is to eat something small every 45 minutes to 1 hour. Your body can absorb 150-300 kCal per hour which is far below the 600-1000 kCal you will be burning (for a reference, one 40g gel is around 100 kCal). Deficit is unavoidable so don&amp;rsquo;t try to sutff yourself and upset your stomach.&lt;/li&gt;
&lt;li&gt;In long races, you want to have a protein intake as well. The recommendation being 2.5g to 10g per hour which helps with the onset of muscle breakdown.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Theory sorted, now let&amp;rsquo;s see if I can put this to practice and finally have a race where stomach issues won&amp;rsquo;t be the limitting factor for performance.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>From logs to traces</title>
      <link>https://dzx.cz/2024-05-01/from-logs-to-traces/</link>
      <pubDate>Wed, 01 May 2024 00:00:00 +0000</pubDate>
      <author>matousdzivjak@gmail.com (Matouš Dzivjak)</author>
      <guid>https://dzx.cz/2024-05-01/from-logs-to-traces/</guid>
      <description>&lt;p&gt;At SumUp we heavily rely on &lt;a href=&#34;https://opentelemetry.io/&#34;&gt;Opentelemetry&lt;/a&gt; tracing and &lt;a href=&#34;https://www.honeycomb.io/&#34;&gt;Honeycomb&lt;/a&gt; for observability. Traces are, in my opinion, far superior tool for debugging and analysis than logs. Yet, there&amp;rsquo;s time and place for everything and sometimes you need to log (e.g. gracfully ignored errors). In such cases, it&amp;rsquo;s helpful to be able to move between logs and traces. With &lt;a href=&#34;https://go.dev/blog/slog&#34;&gt;&lt;code&gt;slog&lt;/code&gt;&lt;/a&gt; (and probably any other structured logging library that supports &lt;code&gt;context.Context&lt;/code&gt;) this becomes metter of 20 lines of code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;otelLogHandler&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;struct&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;slog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Handler&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// WithOTEL wraps the slog handler with OTEL handler that extracts and populates trace and span information&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// on the log.&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;WithOTEL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;h&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;slog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Handler&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;slog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Handler&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;otelLogHandler&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;h&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;h&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;otelLogHandler&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Handle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;slog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Record&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;spanCtx&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;trace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;SpanContextFromContext&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;spanCtx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;IsValid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;AddAttrs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;			&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;slog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;trace.trace_id&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;spanCtx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;TraceID&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;			&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;slog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;trace.span_id&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;spanCtx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;SpanID&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;h&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Handler&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Handle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then when initializing your &lt;code&gt;slog.Handler&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;logger&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;slog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;New&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;WithOTEL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;slog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;NewJSONHandler&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Stdout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;slog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;HandlerOptions&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;AddSource&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Level&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;logLevel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;})))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and you are good to go as long as you use &lt;code&gt;slog.ErrorContext&lt;/code&gt; (and alternatives for other verbosity levels).&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Wiki redesign</title>
      <link>https://dzx.cz/2024-04-03/wiki-redesign/</link>
      <pubDate>Wed, 03 Apr 2024 00:00:00 +0000</pubDate>
      <author>matousdzivjak@gmail.com (Matouš Dzivjak)</author>
      <guid>https://dzx.cz/2024-04-03/wiki-redesign/</guid>
      <description>&lt;p&gt;The &lt;a href=&#34;https://wiki.dzx.cz/&#34;&gt;Wiki&lt;/a&gt; now has a new fresh look. I migrated the whole website to a custom framework - &lt;a href=&#34;https://github.com/matoous/mwp&#34;&gt;mwp&lt;/a&gt; - to be able to customize it as much as I please. &lt;code&gt;mwp&lt;/code&gt; is built in &lt;a href=&#34;https://www.rust-lang.org/&#34;&gt;Rust&lt;/a&gt; on top of &lt;a href=&#34;https://actix.rs/&#34;&gt;actix&lt;/a&gt; (web framework), &lt;a href=&#34;https://maud.lambda.xyz/&#34;&gt;maud&lt;/a&gt; (macro for writing HTML), and &lt;a href=&#34;https://github.com/quickwit-oss/tantivy/&#34;&gt;tantivy&lt;/a&gt; (search). The whole server is then packaged into a docker container and deployed on &lt;a href=&#34;https://fly.io/&#34;&gt;fly.io&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The main goal of the rewrite was to add a search functionality that would allow me (and anyone else) to search for all links in the Wiki in a way that takes into consideration the content of the linked websites. That&amp;rsquo;s done by scraping the links, putting the content into an sqlite database that lives alongside the repository, and indexing everything using &lt;a href=&#34;https://github.com/quickwit-oss/tantivy/&#34;&gt;tantivy&lt;/a&gt; at startup. There&amp;rsquo;s plenty of room for improvement; at the moment the scraping needs to be triggered manually and while the index building is fast, it unnecessarily delays the application startup which is annoying during local development.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Running Zephyr on ESP32</title>
      <link>https://dzx.cz/2024-04-01/running-zephyr-on-esp32/</link>
      <pubDate>Mon, 01 Apr 2024 00:00:00 +0000</pubDate>
      <author>matousdzivjak@gmail.com (Matouš Dzivjak)</author>
      <guid>https://dzx.cz/2024-04-01/running-zephyr-on-esp32/</guid>
      <description>&lt;p&gt;Two weeks ago I started toying around with a development version of &lt;a href=&#34;https://www.sumup.com/en-us/solo-card-reader/&#34;&gt;SumUp Solo&lt;/a&gt; card reader and learning more about embed and hardware in general. Recently, we have launched a new reader, &lt;a href=&#34;https://www.sumup.com/en-ie/solo-lite-card-reader/&#34;&gt;Solo Lite&lt;/a&gt; which runs on &lt;a href=&#34;https://www.zephyrproject.org/&#34;&gt;Zephyr&lt;/a&gt; and seemed like an easier entry-point. I don&amp;rsquo;t have a development Solo Lite at hand but I found a couple unused &lt;a href=&#34;https://www.espressif.com/en/products/socs/esp32&#34;&gt;ESP32 microcontrollers&lt;/a&gt; at home. The task for the weekend was simple: get zephyr up and running on and esp32.&lt;/p&gt;
&lt;p&gt;First, I followed the official &lt;a href=&#34;https://docs.zephyrproject.org/latest/develop/getting_started/index.html&#34;&gt;Getting started&lt;/a&gt; guide. I only diverged in the dependencies installation step, using &lt;a href=&#34;https://nixos.org/&#34;&gt;Nix&lt;/a&gt; instead of &lt;a href=&#34;https://brew.sh/&#34;&gt;Homebrew&lt;/a&gt;. In my &lt;a href=&#34;https://nix-community.github.io/home-manager/&#34;&gt;home-manager&lt;/a&gt; config I added the necessary packages:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nix&#34; data-lang=&#34;nix&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;inputs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;outputs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lib&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;config&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pkgs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;unstable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bleeding-edge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;let&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;username&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;matousdzivjak&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;homeDir&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/Users/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;username&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;in&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;home&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;packages&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;pkgs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;minicom&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;# Modem control and terminal emulation program&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;pkgs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wget&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;pkgs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;python3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;pkgs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ninja&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;# Small build system with a focus on speed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;pkgs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gperf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;pkgs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ccache&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;# Device Tree Compiler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;pkgs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dtc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(I switched to nix + home-manager &lt;a href=&#34;https://dzx.cz/2024-03-10/notes-on-nix/&#34;&gt;quite recently&lt;/a&gt;. If you are interested in my whole config checkout &lt;a href=&#34;https://github.com/matoous/nix-home&#34;&gt;github.com/matoous/nix-home&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Next, I update the binary blobs needed for ESP32:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;west blobs fetch hal_espressif
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With that, the development setup is done and what was left was getting something running on the esp and what&amp;rsquo;s easier than a hello world. Zephyr comes with a hello world sample application, we don&amp;rsquo;t even have to write anything ourselves. The sample hello world app can be build using:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;west build -p always -b esp32_devkitc_wroom zephyr/samples/hello_world
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Resulting into an output ending with:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Generating files from /Users/matousdzivjak/code/github.com/matoous/esp32-zephyr/build/zephyr/zephyr.elf for board: esp32_devkitc_wroom
esptool.py v4.5
Creating esp32 image...
Merged 5 ELF sections
Successfully created esp32 image.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I flashed the ESP32 which was as simple as connecting it to the laptop with and USB-C cable and running:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;west flash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The esp blinks a few times and the flashing is done in a couple of seconds. Theoretically, we have the hello world sample app up and running, but better confirm. For that, I connected to the esp using serial port to check the logs. First, &lt;code&gt;minicom&lt;/code&gt; needed tweeking as the last device I worked with had a different setup:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo minicom -s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This pops up the configuration menu:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; +-----[configuration]------+
| Filenames and paths      |
| File transfer protocols  |
| Serial port setup        |
| Modem and dialing        |
| Screen                   |
| Keyboard and Misc        |
| Save setup as dfl        |
| Save setup as..          |
| Exit                     |
| Exit from Minicom        |
+--------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here one needs to configure the &lt;code&gt;Serial port setup&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;+-----------------------------------------------------------------------+
| A -    Serial Device      : /dev/modem                                |
| B - Lockfile Location     : /var/lock                                 |
| C -   Callin Program      :                                           |
| D -  Callout Program      :                                           |
| E -    Bps/Par/Bits       : 115200 8N1                                |
| F - Hardware Flow Control : No                                        |
| G - Software Flow Control : No                                        |
| H -     RS485 Enable      : No                                        |
| I -   RS485 Rts On Send   : No                                        |
| J -  RS485 Rts After Send : No                                        |
| K -  RS485 Rx During Tx   : No                                        |
| L -  RS485 Terminate Bus  : No                                        |
| M - RS485 Delay Rts Before: 0                                         |
| N - RS485 Delay Rts After : 0                                         |
|                                                                       |
|    Change which setting?                                              |
+-----------------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Fist, &lt;code&gt;A&lt;/code&gt; to modify the &lt;code&gt;Serial device&lt;/code&gt;. We need to specify the &lt;code&gt;tty&lt;/code&gt; of the connected esp. For me this was &lt;code&gt;/dev/tty.usbserial-0001&lt;/code&gt;. I think this might differ for others, so the quick way to check which serial device to use one can run &lt;code&gt;ls /dev | grep &#39;tty.*usb&#39;&lt;/code&gt; and unless there are multiple devices with serial port connected via an USB cable there should be exactly one result.&lt;/p&gt;
&lt;p&gt;Once that&amp;rsquo;s done, &lt;code&gt;Exit&lt;/code&gt;, and here it is:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Welcome to minicom 2.9

OPTIONS: I18n
Compiled on Jan  1 1980, 00:00:00.
Port /dev/tty.usbserial-0001, 22:07:30

Press CTRL-A Z for help on special keys

0020 vaddr=00000020 size=0001ch (    28)
I (113) esp_image: segment 1: paddr=00010044 vaddr=3ffb0000 size=00104h (   260) load
I (122) esp_image: segment 2: paddr=00010150 vaddr=3�NG early entropy source...
*** Booting Zephyr OS build v3.6.0-1966-g3f218c6cdae0 ***
Hello World! esp32_devkitc_wroom/esp32/procpu  
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A beautiful, rewarding, and underwhelming &lt;code&gt;Hello World!&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Next I think I will try to run &lt;code&gt;Hello World!&lt;/code&gt; with &lt;a href=&#34;https://github.com/oxidecomputer/hubris&#34;&gt;hubris&lt;/a&gt; which upon initial investigation seems to be way more complex as esp32 board isn&amp;rsquo;t supported out of the box. Alternatively, I might try to get Zephyr up and running on a Solo instead. Either way, enough for one evening and more to come.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Notes on Nix</title>
      <link>https://dzx.cz/2024-03-10/notes-on-nix/</link>
      <pubDate>Sun, 10 Mar 2024 00:00:00 +0000</pubDate>
      <author>matousdzivjak@gmail.com (Matouš Dzivjak)</author>
      <guid>https://dzx.cz/2024-03-10/notes-on-nix/</guid>
      <description>&lt;p&gt;Over the weekend I switched my MacOS setup in large part from &lt;a href=&#34;https://brew.sh/&#34;&gt;homebrew&lt;/a&gt; to &lt;a href=&#34;https://nixos.org/&#34;&gt;Nix&lt;/a&gt;. You can find the new &lt;em&gt;home&lt;/em&gt; at &lt;a href=&#34;https://github.com/matoous/nix-home&#34;&gt;github.com/matoous/nix-hoome&lt;/a&gt;. To be frank, I know little about Nix which is famous for its steep learning curve so I ended up copying and stitching together code from google and people I follow.&lt;/p&gt;
&lt;p&gt;Nix allows multiple different versions of the same binary to be installed at the same time which helps with avoiding collisions and allows different tools to be updated independently.One can do something similar with &lt;code&gt;homebrew&lt;/code&gt;, e.g. installing Qt version five using: &lt;code&gt;brew install qt@5&lt;/code&gt;, but to my understanding this is way more limiting because of the dependency chain.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;To go over historical versions of specific package see &lt;a href=&#34;https://lazamar.co.uk/nix-versions/?channel=nixpkgs-unstable&amp;amp;package=nodejs&#34;&gt;nix-versions&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Install the package using &lt;code&gt;nix-env -iA&lt;/code&gt;, e.g. &lt;code&gt;nix-env -iA nodejs_20 -f https://github.com/NixOS/nixpkgs/archive/9957cd48326fe8dbd52fdc50dd2502307f188b0d.tar.gz&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Previously, nix used multiple different command for different things. E.g. &lt;code&gt;nix-env&lt;/code&gt; for installing packages into the environment, &lt;code&gt;nix-shell&lt;/code&gt; to init a nix shell, etc. Nowadays, all these commands are available under the &lt;code&gt;nix&lt;/code&gt; command which you need to enable using &lt;code&gt;~/.config/nix/nix.conf&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-conf&#34; data-lang=&#34;conf&#34;&gt;experimental-features = nix-command flakes
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There are a few promising things about Nix that I want to explore:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;With nix it is easy to provision developer environment per-repository. One can do so by adding a &lt;a href=&#34;https://nixos.wiki/wiki/Flakes&#34;&gt;flake&lt;/a&gt; that configures all required tools for development.&lt;/li&gt;
&lt;li&gt;There&amp;rsquo;s &lt;a href=&#34;https://nixos.org/manual/nixos/stable/&#34;&gt;NixOS&lt;/a&gt; which allow whole OS to be declaratively configured using Nix.&lt;/li&gt;
&lt;li&gt;You can build packages using Nix which builds them in isolations using specific versions of dependencies which ensures that you will get a consistent result.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;rsquo;s it for now, I will keep on toying around with Nix and see what more there is to it. For now, I manage my dot files and tools using &lt;a href=&#34;https://github.com/nix-community/home-manager&#34;&gt;home-manager&lt;/a&gt; and started experimenting with using Nix to cross-compile software for &lt;a href=&#34;https://www.sumup.com/en-us/solo-card-reader/&#34;&gt;Solo&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>CRDTs</title>
      <link>https://dzx.cz/2024-02-17/crdts/</link>
      <pubDate>Sat, 17 Feb 2024 00:00:00 +0000</pubDate>
      <author>matousdzivjak@gmail.com (Matouš Dzivjak)</author>
      <guid>https://dzx.cz/2024-02-17/crdts/</guid>
      <description>&lt;p&gt;In a recent side-project attempt to built an RFC management tool I ventured into the topic of &lt;a href=&#34;https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type&#34;&gt;CRDTs&lt;/a&gt; (Conflict-free Replicated Data Type) and web-based text editors. Here is a loose collection of links to various tools and articles on the topic:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://jakelazaroff.com/words/an-interactive-intro-to-crdts/&#34;&gt;An Interactive Intro to CRDTs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://marijnhaverbeke.nl/blog/collaborative-editing.html&#34;&gt;Collaborative Editing in ProseMirror&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://interjectedfuture.com/crdts-turned-inside-out/&#34;&gt;CRDTs Turned Inside Out&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.inkandswitch.com&#34;&gt;Ink and Switch&lt;/a&gt; - Articles on collaborative peer-to-peer editing.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vlcn.io/blog/gentle-intro-to-crdts.html&#34;&gt;A Gentle Introduction to CRDTs (Conflict Free Replicated Data types (CRDTs))&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Implementation&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://nomad.foo/blog/cola&#34;&gt;cola: a text CRDT for real-time collaborative editing&lt;/a&gt; - leightweight CRDT implemention in rust for plain text documents.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/loro-dev/loro&#34;&gt;Loro&lt;/a&gt; - feature-rich CRDT implemention for rich-text documents in rust.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/y-crdt&#34;&gt;y-crdt&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Editors&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://codemirror.net/&#34;&gt;CodeMirror&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://prosemirror.net/&#34;&gt;ProseMirror&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://quilljs.com&#34;&gt;Quill&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Inception</title>
      <link>https://dzx.cz/2024-02-16/inception/</link>
      <pubDate>Fri, 16 Feb 2024 00:00:00 +0000</pubDate>
      <author>matousdzivjak@gmail.com (Matouš Dzivjak)</author>
      <guid>https://dzx.cz/2024-02-16/inception/</guid>
      <description>&lt;p&gt;This is the inception of &lt;a href=&#34;https://dzx.cz/atoms&#34;&gt;Atoms&lt;/a&gt; - a short-form stream of notes and thoughts inspired by Tom MacWrigth&amp;rsquo;s &lt;a href=&#34;https://macwright.com/micro/&#34;&gt;Micro&lt;/a&gt; and Brandur Leach&amp;rsquo;s &lt;a href=&#34;https://brandur.org/atoms&#34;&gt;Atoms&lt;/a&gt; and &lt;a href=&#34;https://brandur.org/fragments&#34;&gt;Fragments&lt;/a&gt;. Atoms will serve the void between notes in the &lt;a href=&#34;https://wiki.dzx.cz/&#34;&gt;Wiki&lt;/a&gt; (currently undergoing a rewrite) and &lt;a href=&#34;http://localhost:1313/posts/&#34;&gt;longer posts&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can subscribe to atoms using the &lt;a href=&#34;https://dzx.cz/atoms/index.xml&#34;&gt;RSS Feed&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
