<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jan David</title>
    <description>The latest articles on DEV Community by Jan David (@jdno).</description>
    <link>https://dev.to/jdno</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F438602%2Facc306da-ffec-40b6-9a77-d3d23647b1f3.jpeg</url>
      <title>DEV Community: Jan David</title>
      <link>https://dev.to/jdno</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jdno"/>
    <language>en</language>
    <item>
      <title>DEV x BOTS</title>
      <dc:creator>Jan David</dc:creator>
      <pubDate>Mon, 08 Aug 2022 16:00:03 +0000</pubDate>
      <link>https://dev.to/devxbots/dev-x-bots-57mk</link>
      <guid>https://dev.to/devxbots/dev-x-bots-57mk</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vn3tw1cd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/08/Banner-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vn3tw1cd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/08/Banner-1.png" alt="DEV x BOTS" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I look back on the side projects that I started and abandoned over the past few years, and the notes and drawings that I added to my notebook, a clear pattern emerges. Some ideas got way more attention than others, and a handful actually came up again and again. I would spend a few weeks thinking about them, eventually putting them away, but a few months later they always returned.&lt;/p&gt;

&lt;p&gt;In one way or another, these ideas were all focused on my experience as a software developer. As I was working on other projects, I always noticed things that could be easier or better. More efficient CI workflows, better local development environments, automation to help manage open source projects. Eventually, I would always get so fed up that I wanted to build a tool that would solve that problem for me.&lt;/p&gt;

&lt;p&gt;A few times, I did start working on such a tool. But I never made a plan, set boundaries, or defined a goal. And as I got deeper into the problem space, I realized what else was possible. How this tool could be so much more than I initially thought. But as I enjoyed jumping from idea to idea, the scope of the projects grew in so many different directions that it would ultimately cause them to fail. I was more interested in intellectual stimulation than delivering something of value.&lt;/p&gt;

&lt;p&gt;I don't know why and when, but this has changed recently. I feel like I did enough experimentation, and the next big thing for me to learn is to deliver and then operate a product. To talk with other developers and teams, and help them improve their workflows. This is the fundamental idea behind my new project, &lt;a href="https://github.com/devxbots"&gt;DEV x BOTS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/devxbots"&gt;https://github.com/devxbots&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Automatons – Automation for Developers
&lt;/h2&gt;

&lt;p&gt;The focus of &lt;a href="https://github.com/devxbots"&gt;DEV x BOTS&lt;/a&gt; is the development of an automation platform for software developers called &lt;code&gt;automatons&lt;/code&gt;. Looking back at my failed ideas and projects, they were all trying to automate various parts of the software development process. But building bespoke automation is time consuming work, and it really shouldn't be.&lt;/p&gt;

&lt;p&gt;Learning from past mistakes, the project is set up to deliver small, concrete results that build on top of each other. While the ultimate goal is to deliver an automation platform, the first step is to create a library. Then I want to create a few custom &lt;a href="https://docs.github.com/en/developers/apps"&gt;GitHub Apps&lt;/a&gt;, finally building some of the ideas that have been floating around my notes for years. Any feature that the apps need will find its way back into the library, slowly growing its scope and usability. And the apps need to run somewhere, which means another deliverable is a runtime for them. The combination of library and runtime will be the &lt;em&gt;minimum viable product&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I expect to learn a lot during this process, which will influence the future direction of the project. But in a nutshell, I want to broaden the feature set of the framework and move away from bespoke apps. Developers should be able to automate workflows that go beyond just &lt;a href="https://github.com"&gt;GitHub&lt;/a&gt;, for example integrate their project management in &lt;a href="https://linear.app/"&gt;Linear&lt;/a&gt;. And creating an automation shouldn't involve a custom GitHub App, but maybe just a configuration file in a repository. Which would be cool to create using a visual flow-based builder, similar to &lt;a href="https://docs.unrealengine.com/5.0/en-US/blueprints-visual-scripting-in-unreal-engine/"&gt;Blueprints in Unreal Engine&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All of this will take time to build, which is why there is a focus on small steps and iteration. Slowly working towards the &lt;em&gt;minimum viable product&lt;/em&gt;, and then figuring out the necessary features for a &lt;em&gt;simple, lovable &amp;amp; complete product&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Committed to Open Source
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;automatons&lt;/code&gt; framework is developed as open source, and the goal is to (eventually) offer self-hosted runtimes so that teams can run the full stack themselves. Check out DEV x BOTS's GitHub profile and the project:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/devxbots"&gt;https://github.com/devxbots&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Besides just being a fan of open source myself, I am doing this for three reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Developers should be able to trust the tool. This means that they can inspect the source code and ensure that it is safe to run.&lt;/li&gt;
&lt;li&gt;Developers should be able to rely on the tool. With open source, they will always be able to run the tool themselves, no matter what happens with me. There is no &lt;a href="https://en.wikipedia.org/wiki/Vendor_lock-in"&gt;vendor lock-in&lt;/a&gt;, and less of a &lt;a href="https://en.wikipedia.org/wiki/Bus_factor"&gt;bus factor&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Developers should be able to contribute and solve their own problems. My priorities might not be your priorities. But with everything being open source, you can solve your problem and contribute the solution back to the community.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The commitment to open source also covers the usage of the platform. I will run an instance of the service that open source projects can use for free. But contributions to cover the development and server costs are greatly appreciated:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/sponsors/jdno"&gt;https://github.com/sponsors/jdno&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Up
&lt;/h2&gt;

&lt;p&gt;The next blog post will introduce the &lt;code&gt;automatons&lt;/code&gt; framework itself, and the considerations that went into its design. We will look at its core library, and the prototype for an GitHub App that uses it. Until then, take care and have fun!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blog: &lt;a href="https://jdno.dev"&gt;https://jdno.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/jdno"&gt;https://github.com/jdno&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Twitter: &lt;a href="https://twitter.com/jdno_dev"&gt;https://twitter.com/jdno_dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Twitch: &lt;a href="https://www.twitch.tv/jdno_dev"&gt;https://twitch.tv/jdno_dev&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>Auto Traffic Control – Version 0.2.0</title>
      <dc:creator>Jan David</dc:creator>
      <pubDate>Sun, 17 Apr 2022 16:00:00 +0000</pubDate>
      <link>https://dev.to/jdno/auto-traffic-control-version-020-3mjj</link>
      <guid>https://dev.to/jdno/auto-traffic-control-version-020-3mjj</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c2DDmsqJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/04/v0.2.0-copy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c2DDmsqJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/04/v0.2.0-copy.png" alt="Auto Traffic Control – Version 0.2.0" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Revisiting 0.1.0
&lt;/h2&gt;

&lt;p&gt;The previous version of the game, 0.1.0, was also its first release. This version was never released to the public, and only used internally for testing. It featured the first playable prototype of the game, but it was still missing many important features.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4dqH7Yni--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/04/v0.1.0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4dqH7Yni--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/04/v0.1.0.png" alt="Auto Traffic Control – Version 0.2.0" width="880" height="753"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Version 0.1.0 had a single airport at the center of the map (green square), a routing grid, and planes (red squares) that spawned at random locations on the edge of the routing grid. The location of the airport was hard-coded, and my bot used simple &lt;a href="https://en.wikipedia.org/wiki/Euclidean_geometry"&gt;Euclidean geometry&lt;/a&gt; to calculate a flight plan to the center of the map.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Changed
&lt;/h2&gt;

&lt;p&gt;The most obvious change between version 0.1.0 and 0.2.0 are the graphics. The second release features simple sprites for the background, the airport, and the airplanes.&lt;/p&gt;

&lt;p&gt;The game also introduced two different colors for airplanes and airports. Players have to route airplanes to the airport that matches their color to score a point. This made it easier to have more airplanes on the map, while avoiding congestion issues around the airport. And more airplanes make the game more dynamic and lively, which I believe will lead to more fun playing the game.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--l52che6V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/04/v0.2.0-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--l52che6V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/04/v0.2.0-1.png" alt="Auto Traffic Control – Version 0.2.0" width="880" height="753"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The introduction of two airports in different colors also required changes to the API. The map API in particular was extended significantly to allow players to query the map with the different airports and the routing grid.&lt;/p&gt;

&lt;p&gt;Lastly, the release of the game is accompanied by a new website for the game. The website contains documentation on installing the game, its rules, and on its API with the different message types and services. A &lt;a href="https://auto-traffic-control.com/docs"&gt;Quickstart&lt;/a&gt; guide is designed to help getting started with the game, although it is admittedly still very rough around the edges.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://auto-traffic-control.com"&gt;https://auto-traffic-control.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check out the full release notes for a comprehensive list of changes in this release: &lt;a href="https://github.com/jdno/auto-traffic-control/releases/tag/v0.2.0"&gt;https://github.com/jdno/auto-traffic-control/releases/tag/v0.2.0&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Plans for 0.3.0+
&lt;/h2&gt;

&lt;p&gt;The focus for the next release of the game is the addition of a Node.js client library. This will make it easy to play the game in either JavaScript or TypeScript, or any other language with support for npm packages.&lt;/p&gt;

&lt;p&gt;I also plan to improve the documentation with a tutorial for TypeScript. The tutorial will walk through the first steps in playing the game, from installation to first playthrough. This is a great test for the game's npm package, and it will make it easier for new players to get started.&lt;/p&gt;

&lt;p&gt;After that the plans are a bit fuzzy. There are a few game mechanics that I'd like to implement, for example &lt;em&gt;priority airplanes&lt;/em&gt; that have a fixed flight plan and that cannot be controlled by the player. I'd also like to experiment with different map features, e.g. cities over which airplanes are not allowed to fly. And the game needs a better UI, but how to build that is still a very big question mark. We'll see what to do after 0.3.0 is released...&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow the Project
&lt;/h2&gt;

&lt;p&gt;Check out &lt;a href="https://auto-traffic-control.com"&gt;Auto Traffic Control&lt;/a&gt; on &lt;a href="https://jdno.itch.io/auto-traffic-control"&gt;itch.io&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://jdno.itch.io/auto-traffic-control"&gt;https://jdno.itch.io/auto-traffic-control&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're interesting in my game &lt;a href="https://dev.to/jdno/auto-traffic-control-a-video-game-for-programmers-f9k"&gt;Auto Traffic Control&lt;/a&gt; or programming games in general, make sure to follow along. I am not sure where the road will take us, but I am very excited for the journey!&lt;/p&gt;

&lt;p&gt;Subscribe to my blog to receive weekly updates about the progress on the project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://jdno.dev"&gt;jdno.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also stream some if not all of the development of this game on Twitch, so follow me there as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.twitch.tv/jdno_dev"&gt;jdno_dev - Twitch&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>opensource</category>
      <category>rust</category>
    </item>
    <item>
      <title>Automate Building and Publishing a Game on itch.io</title>
      <dc:creator>Jan David</dc:creator>
      <pubDate>Sun, 10 Apr 2022 16:00:00 +0000</pubDate>
      <link>https://dev.to/jdno/automate-building-and-publishing-a-game-on-itchio-5c46</link>
      <guid>https://dev.to/jdno/automate-building-and-publishing-a-game-on-itchio-5c46</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M_-39Hyt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/04/github-to-itch.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M_-39Hyt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/04/github-to-itch.png" alt="Automate Building and Publishing a Game on itch.io" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I really like automation in software development (and elsewhere). And since my personal projects are hosted on &lt;a href="https://github.com/"&gt;GitHub&lt;/a&gt;, I have fully adopted &lt;a href="https://github.com/features/actions"&gt;GitHub Actions&lt;/a&gt; as my continuous integration platform. When I push code, a handful of actions is started that lint the code, check its style, and run automated tests. When they all pass, it gives me confidence in the quality of my work.&lt;/p&gt;

&lt;p&gt;For my upcoming game &lt;a href="https://dev.to/jdno/auto-traffic-control-a-video-game-for-programmers-f9k"&gt;Auto Traffic Control&lt;/a&gt;, I wanted to use GitHub Actions again to create reproducible builds of the game with a predictable and consistent quality. The goal was to avoid human error by fully automating the process, from build to release on &lt;a href="https://itch.io"&gt;itch.io&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a New Action
&lt;/h2&gt;

&lt;p&gt;I recommend creating a new action for this workflow. Especially if you want to build your game for multiple operating systems, the file will get pretty long as is. Go ahead and create a new YAML file in &lt;code&gt;.github/workflows/itch.yml&lt;/code&gt;, and add the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;itch.io&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;itch_project&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jdno/auto-traffic-control&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change the &lt;code&gt;itch_project&lt;/code&gt; string to match your username on &lt;a href="https://itch.io"&gt;itch.io&lt;/a&gt; and the name of your project. If you like, you can also change the name of the action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trigger a Release
&lt;/h2&gt;

&lt;p&gt;The setup that I have developed over the years for my GitHub Actions has one important feature: It has different actions for different workflows.&lt;/p&gt;

&lt;p&gt;When I push code to GitHub, actions are started that check the quality of the code. These checks have to pass before I can merge the code into the &lt;code&gt;main&lt;/code&gt; branch. Their purpose is to ensure a consistent code quality, not to create a release.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5CypsEUG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/04/Screenshot-2022-04-10-at-17.16.40.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5CypsEUG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/04/Screenshot-2022-04-10-at-17.16.40.png" alt="Automate Building and Publishing a Game on itch.io" width="880" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I want to create a new release, I actually use the &lt;a href="https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases"&gt;release feature&lt;/a&gt; on GitHub. I like writing a short summary of what's changed, and include a changelog in the release notes. It makes the release feel more "official", and like an actual achievement. When I create a release, another action is kicked off that builds the game in &lt;code&gt;release&lt;/code&gt; mode, and then pushes the game to &lt;a href="https://itch.io"&gt;itch.io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The following snippet is what I use to trigger my release workflow. It runs the action whenever a pre-release or release is published on GitHub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;on"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;prereleased&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;released&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also build and publish the game every time code is merged into the default branch with a snippet like below. The choice is ultimately yours, and depends on what makes sense for your development workflow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;on"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Build the Game
&lt;/h2&gt;

&lt;p&gt;The build step depends on your game, and I cannot give you advice on it. The steps will look different based on the programming language or game engine that you use. On a high level, though, you want to do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check out the code&lt;/li&gt;
&lt;li&gt;Set up a build environment&lt;/li&gt;
&lt;li&gt;Compile the game&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The following examples assume that you also copy the binary and any resources/assets that the game needs into a &lt;code&gt;dist&lt;/code&gt; folder. This is the folder that will be pushed to &lt;a href="https://itch.io"&gt;itch.io&lt;/a&gt;. What needs to go into this folder again depends on the game engine that you are using.&lt;/p&gt;

&lt;p&gt;I create builds of my game for Linux, macOS, and Windows. Each operating system requires slightly different dependencies, so I decided to split the build into three different jobs: one for each operating system. Below is the Linux build as an example. The job installs the dependencies, checks out the code, sets up the Rust toolchain, and then builds the game.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;linux&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish Linux build&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install system dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install -y \&lt;/span&gt;
          &lt;span class="s"&gt;libx11-dev \&lt;/span&gt;
          &lt;span class="s"&gt;libasound2-dev \&lt;/span&gt;
          &lt;span class="s"&gt;libudev-dev&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout code&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Rust toolchain&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions-rs/toolchain@v1&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build release artifact&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions-rs/cargo@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
          &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;--release&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After these steps, the release artifact will be copied into the &lt;code&gt;dist&lt;/code&gt; folder along with the assets that my game use. Theoretically, I can now run my game from this folder and it would work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Publish to itch.io
&lt;/h2&gt;

&lt;p&gt;The final step is publishing the game to &lt;a href="https://itch.io"&gt;itch.io&lt;/a&gt;. We will be using itch's &lt;a href="https://itch.io/docs/butler/"&gt;butler&lt;/a&gt;, a tool that makes it easy to upload games to itch. This is the command to publish a new version of a game:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;butler push directory user/game:channel &lt;span class="nt"&gt;--userversion&lt;/span&gt; version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command takes a &lt;code&gt;directory&lt;/code&gt; as its argument, and uploads the contents of this directory to &lt;a href="https://itch.io"&gt;itch.io&lt;/a&gt;. This will be our &lt;code&gt;dist&lt;/code&gt; directory. The next argument is the project, which we've set at the beginning in the &lt;code&gt;itch_project&lt;/code&gt; variable, followed by the channel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://itch.io/docs/butler/pushing.html#channel-names"&gt;Channels&lt;/a&gt; are an important concept on &lt;a href="https://itch.io"&gt;itch.io&lt;/a&gt;, and the channel name can be used to automatically tag the game on the platform. For example, pushing to the &lt;code&gt;linux&lt;/code&gt; channel will tag the game as a Linux executable.&lt;/p&gt;

&lt;p&gt;Lastly, we pass the optional &lt;code&gt;userversion&lt;/code&gt; argument. The goal is to use the same version number on GitHub and on itch.io.&lt;/p&gt;

&lt;p&gt;I am getting these variables from the release that I created on GitHub. When a release is published and the action is started, GitHub will add the release to the action's &lt;a href="https://docs.github.com/en/actions/learn-github-actions/contexts"&gt;context&lt;/a&gt;. This makes it possible, for example, to access the title of the release with &lt;code&gt;github.event.release.name&lt;/code&gt; (which is &lt;code&gt;0.1.0&lt;/code&gt; for this release). If you want to run the action on every commit (i.e. &lt;code&gt;on: [push]&lt;/code&gt; above), you need to either hard-code them or find another way to provide them dynamically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set version&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo "version=${{ github.event.release.name }}" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set beta channel&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.event.action == 'prereleased'&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo "itch_channel=linux-beta" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set release channel&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.event.action == 'released'&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo "itch_channel=linux-stable" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I am particularly proud of finding a way to support pre-releases. When a release is tagged as a pre-release on GitHub, the game will be pushed to the &lt;code&gt;beta&lt;/code&gt; channel. This makes it easy for me to test a new version of the game, before making it generally available.&lt;/p&gt;

&lt;p&gt;Now that we have set the variables that are required to run &lt;code&gt;butler&lt;/code&gt;, we can first add the tool to our workflow and then run it. Pushing a build to &lt;a href="https://itch.io"&gt;itch.io&lt;/a&gt; requires an API key, which you can &lt;a href="https://itch.io/docs/butler/login.html#running-butler-from-ci-builds-travis-ci-gitlab-ci-etc"&gt;find here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up butler&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;jdno/setup-butler@v1&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish game to itch.io&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;butler push dist ${{ env.itch_project }}:${{ env.itch_channel }} --userversion ${{ env.version }}&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;BUTLER_API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.ITCHIO_API_KEY }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A new version of your game is now available on &lt;a href="https://itch.io"&gt;itch.io&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Profit
&lt;/h2&gt;

&lt;p&gt;This is admittedly an advanced action with some pretty complex steps. Getting it to work correctly for your project might require a few iterations. It took me many builds to get this right. But the results are great, and totally worth the effort!&lt;/p&gt;

&lt;p&gt;Most importantly, you now have a reproducible build. Getting your game ready for release is not a dark art anymore, nor does it require finding the note with the instructions somewhere on your desk. You can just look at the action to see which steps are required to build and then push the game.&lt;/p&gt;

&lt;p&gt;Because the build is automated, it is also guaranteed to produce consistent results. Your local development environment cannot break the build or the game in mysterious ways, because the build environment is always clean.&lt;/p&gt;

&lt;p&gt;And you know that everything that is required to build the game is backed up on GitHub. All code and all assets are safely stored in a second place, with a version history.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow me
&lt;/h2&gt;

&lt;p&gt;If you're interesting in my game &lt;a href="https://dev.to/jdno/auto-traffic-control-a-video-game-for-programmers-f9k"&gt;Auto Traffic Control&lt;/a&gt; or programming games in general, make sure to follow along. I am not sure where the road will take us, but I am very excited for the journey!&lt;/p&gt;

&lt;p&gt;Subscribe to my blog to receive weekly updates about the progress on the project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://jdno.dev"&gt;jdno.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also stream some if not all of the development of this game on Twitch, so follow me there as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.twitch.tv/jdno_dev"&gt;jdno_dev - Twitch&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>githubaction</category>
      <category>github</category>
    </item>
    <item>
      <title>Designing an API for a Video Game</title>
      <dc:creator>Jan David</dc:creator>
      <pubDate>Sun, 13 Mar 2022 17:00:00 +0000</pubDate>
      <link>https://dev.to/jdno/designing-an-api-for-a-video-game-4jn</link>
      <guid>https://dev.to/jdno/designing-an-api-for-a-video-game-4jn</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jiZkr-Gs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1599110906632-28d25094470f%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDEwfHxibHVlcHJpbnR8ZW58MHx8fHwxNjQ3MTYwOTIy%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jiZkr-Gs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1599110906632-28d25094470f%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDEwfHxibHVlcHJpbnR8ZW58MHx8fHwxNjQ3MTYwOTIy%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" alt="Designing an API for a Video Game" width="880" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am working on a video game for programmers. The game is played by writing code that interacts with the game through an API. This post explores the design of the API that connects the player's code, the API layer, and the game simulation.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Video Game for Programmers
&lt;/h2&gt;

&lt;p&gt;I have been thinking about a &lt;a href="https://www.jdno.dev/why-i-want-to-build-a-video-game-for-programmers/"&gt;video game for programmers&lt;/a&gt; for a while now. What differentiates such a game from others is that it is played by writing code. The player cannot interact with the game world themselves but only through an API. Essentially, they create a program that plays the game for them.&lt;/p&gt;

&lt;p&gt;The time has come to make this dream a reality and build a working game. I am working on &lt;a href="https://dev.to/jdno/auto-traffic-control-a-video-game-for-programmers-f9k"&gt;Auto Traffic Control (ATC)&lt;/a&gt;, a game in which players have to safely route airplanes to an airport.&lt;/p&gt;

&lt;h2&gt;
  
  
  ATC as a Distributed System
&lt;/h2&gt;

&lt;p&gt;Over the past two years, I experimented with different ideas for the API and the architecture of the game. One prototype had a &lt;a href="https://en.wikipedia.org/wiki/Representational_state_transfer"&gt;REST&lt;/a&gt; interface, another tried to wire RPC calls into the core loop inside the game engine, and there were a few that explored various asynchronous interfaces such as message queues. But all of them eventually ran into problems, with a root cause that in hindsight is totally obvious:&lt;/p&gt;

&lt;p&gt;At its core, the game that I want to build is a &lt;a href="https://en.wikipedia.org/wiki/Distributed_computing"&gt;distributed system&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are three components that are independent of each other: the player's code, the API layer, and the game simulation. The player's code runs in its own process and is totally decoupled from the game. But even the API layer and the game simulation are only loosely coupled, and run in parallel in different threads. The result is a system in which all components run concurrently, and any attempt to introduce tight coupling between them is bound to fail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Event Sourcing and CQRS
&lt;/h2&gt;

&lt;p&gt;The architecture for the game takes a lot of inspiration from &lt;a href="https://danielwhittaker.me/2020/02/20/cqrs-step-step-guide-flow-typical-application/"&gt;Event Sourcing and CQRS&lt;/a&gt;. The player sends a &lt;em&gt;command&lt;/em&gt; to the API, which validates it and then puts it into a queue. The different systems that power the simulation inside the game take commands from the queue, and make the corresponding change to the simulation. The change in turn triggers an &lt;em&gt;event&lt;/em&gt;, which is send back to the API via another queue. The API receives the event, and sends it over a stream to the player.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--16Qr-hyL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/03/2022-03-13-ATC-Architecture.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--16Qr-hyL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/03/2022-03-13-ATC-Architecture.png" alt="Designing an API for a Video Game" width="880" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The diagram above visualizes this architecture inside the game. The API on the left has different services that each manage a single resource. The event source streams events to the player, while the airplane service allows players to interact with the airplanes in the game. The API is coupled with the simulation on the right through two queues: the &lt;em&gt;event bus&lt;/em&gt; and the &lt;em&gt;command bus&lt;/em&gt;. The game is built with the game engine &lt;a href="https://bevyengine.org/"&gt;Bevy&lt;/a&gt;,  which runs many &lt;em&gt;systems&lt;/em&gt; in parallel to simulate the game. All systems are connected to the event bus so that they can publish any change they make to the game world. And systems that can be influenced by the player are connected to the command bus as well.&lt;/p&gt;

&lt;p&gt;This architecture has worked really well in experiments, and I can't wait to see how well it'll work for a full game. Stay tuned to learn more about that in the future!&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow the Project
&lt;/h2&gt;

&lt;p&gt;If you're interesting in this game or programming games in general, make sure to follow along. I am not sure where the road will take us, but I am very excited for the journey!&lt;/p&gt;

&lt;p&gt;Subscribe to my blog to receive weekly updates about the progress on the project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://jdno.dev"&gt;jdno.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also stream some if not all of the development of this game on Twitch, so follow me there as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.twitch.tv/jdno_dev"&gt;jdno_dev - Twitch&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>devlog</category>
    </item>
    <item>
      <title>Auto Traffic Control – A Video Game for Programmers</title>
      <dc:creator>Jan David</dc:creator>
      <pubDate>Sun, 06 Mar 2022 17:00:00 +0000</pubDate>
      <link>https://dev.to/jdno/auto-traffic-control-a-video-game-for-programmers-f9k</link>
      <guid>https://dev.to/jdno/auto-traffic-control-a-video-game-for-programmers-f9k</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o9AoKHx4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1608444331927-05052bef8884%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDV8fGF0Y3xlbnwwfHx8fDE2NDY1NzM1MzM%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o9AoKHx4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1608444331927-05052bef8884%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDV8fGF0Y3xlbnwwfHx8fDE2NDY1NzM1MzM%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" alt="Auto Traffic Control – A Video Game for Programmers" width="880" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Auto Traffic Control, fittingly abbreviated ATC, is my next project and a video game for programmers about safely routing planes to an airport. It takes inspiration from the old school hit Flight Control, and adapts its game mechanics for programming.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Video Game for Programmers
&lt;/h2&gt;

&lt;p&gt;I have thought, talked, and written about programming and video games a lot over the past two years. The intersection of the two is still super interesting to me, and I truly believe that we can make software development as a field more accessible by making it more fun. The following piece captures a lot of my thoughts on the topic:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.jdno.dev/why-i-want-to-build-a-video-game-for-programmers/"&gt;Why I Want to Build a Video Game for Programmers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After quite some exploration and experimentation, I think that I have learned enough to make a serious attempt at developing a small video game for programmers. The next four weeks are all about going from idea to prototype, and testing the hypothesis that video games for programmers can be fun!&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspired by Flight Control
&lt;/h2&gt;

&lt;p&gt;One inspiration for the game is the old school hit &lt;a href="https://en.wikipedia.org/wiki/Flight_Control_(video_game)"&gt;Flight Control&lt;/a&gt;, which was one of my favorite games on mobile. I still have a lot of very fond memories of spending hours playing the game on an iPad, back in 2012.&lt;/p&gt;

&lt;p&gt;In Flight Control, the player is in control of an airport and its surrounding area. Airplanes enter the map from the side and fly around randomly. The player has to create a path for each plane that brings it safely to the airport. When two planes collide, the game ends. When a plane reaches the airport, it lands and disappears, and the player gets a point.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UvBckMgJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/03/ss_1b9bf9a081c41b4e7b10ec1811aafc725cb3d7dd.1920x1080.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UvBckMgJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/03/ss_1b9bf9a081c41b4e7b10ec1811aafc725cb3d7dd.1920x1080.jpg" alt="Auto Traffic Control – A Video Game for Programmers" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Flight_Control_(video_game)"&gt;Flight Control&lt;/a&gt; had a few more features that made the games more fun and/or challenging. Most maps features three different kinds of aircraft: small planes, bigger planes, and helicopters. They had different speeds, and had to be routed to different runways. There was changing wind that determined which runways were open, requiring the player to ever so often redraw all routes. And there were high priority planes, which followed a fixed route that the player couldn't change. Instead, players had to move their own aircraft out of the way in time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspired by Sector 33
&lt;/h2&gt;

&lt;p&gt;Another game that I played on the iPad back in the days was &lt;a href="https://www.nasa.gov/centers/ames/Sector33/iOS/index.html"&gt;Sector 33&lt;/a&gt;. It featured a similar setting, but with different game mechanics. Players controlled airplanes approaching the San Francisco airport, and had to change their routes and speed to get them safely in a queue and then to the ground.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MXIraKIP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/03/616722main_gamescreen1.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MXIraKIP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/03/616722main_gamescreen1.PNG" alt="Auto Traffic Control – A Video Game for Programmers" width="880" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I don't have as many memories of playing Sector 33 as I have of Flight Control. What I do remember is doing a lot of quick math in my head to perfectly queue up the aircraft. It was very rewarding to get the timing right and have planes slot in perfectly after each other on their approach to SFO.&lt;/p&gt;

&lt;p&gt;Plus, it was just cool to play a video game developed by NASA.&lt;/p&gt;

&lt;h2&gt;
  
  
  Made for Programmers
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Auto Traffic Control&lt;/em&gt; takes inspiration from &lt;a href="https://en.wikipedia.org/wiki/Flight_Control_(video_game)"&gt;Flight Control&lt;/a&gt; and &lt;a href="https://www.nasa.gov/centers/ames/Sector33/iOS/index.html"&gt;Sector 33&lt;/a&gt;, and remixes these games for programming. Instead of drawing on a screen, players create flight plans through an API. And algorithms replace mental arithmetics, hopefully leading to less mid-air collisions than what my 18-year-old me was responsible for.&lt;/p&gt;

&lt;p&gt;The core game loop is similar to Flight Control. The map features one or more airports, and planes fly onto the map from the sides. The player has to provide a flight plan for each plane that lands it safely at the right airport. Landing a plane yields a point, while collisions end the game.&lt;/p&gt;

&lt;p&gt;The difference to &lt;a href="https://en.wikipedia.org/wiki/Flight_Control_(video_game)"&gt;Flight Control&lt;/a&gt; and &lt;a href="https://www.nasa.gov/centers/ames/Sector33/iOS/index.html"&gt;Sector 33&lt;/a&gt; is in how the player interacts with the game. Instead of drawing on the screen or pressing a button, they will call an API to update the flight plan of a plane.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xtA5oroG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/03/2022-03-05-Milestone-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xtA5oroG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2022/03/2022-03-05-Milestone-1.png" alt="Auto Traffic Control – A Video Game for Programmers" width="880" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above wireframe shows an early concept for the game's routing grid. Three planes are approaching the airport at the center of the map. Their flight plans, the black dotted lines, follow the routing grid from node to node. The API to update a flight plan might end up looking like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;flight_number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AT-3245&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;flight_plan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update_flight_plan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;flight_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;flight_plan&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Based on previous experiments, the API will be built around &lt;a href="https://danielwhittaker.me/2020/02/20/cqrs-step-step-guide-flow-typical-application/"&gt;event sourcing and CQRS patterns&lt;/a&gt;. The game will publish events about anything that changes in the simulation, e.g. a new plane entering the map. And players can control the game through commands, which themselves lead to changes that will trigger events. This creates an asynchronous coupling between the game's simulation, the API, and the player's code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Roadmap
&lt;/h2&gt;

&lt;p&gt;The goal is to have a working prototype ready by the end of March. The first two weeks will be focused on technical implementation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Develop a simulation that spawns, flies, and lands planes&lt;/li&gt;
&lt;li&gt;Interact with the game through a bi-directional API&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once these two tasks are done, players can observe the game and change its state through the API. This makes it possible to focus on the core game loop, and experiment with different ideas to make it engaging.&lt;/p&gt;

&lt;p&gt;At the end of the month, I want to know if a game like this is feasible and fun. If so, I might want to turn the prototype into a polished game next. If not, time to go back to the drawing board and figure out where things went wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow the Project
&lt;/h2&gt;

&lt;p&gt;If you're interesting in this game or programming games in general, make sure to follow along. I am not sure where the road will take us, but I am very excited for the journey!&lt;/p&gt;

&lt;p&gt;Subscribe to my blog to receive weekly updates about the progress on the project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://jdno.dev"&gt;jdno.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am also planning to stream some if not all of the development of this game on Twitch, so follow me there as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.twitch.tv/jdno_dev"&gt;jdno_dev - Twitch&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And I'm on Twitter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/jdno_dev"&gt;@jdno_dev&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>rust</category>
      <category>devlog</category>
    </item>
    <item>
      <title>Four Weeks of Experiments</title>
      <dc:creator>Jan David</dc:creator>
      <pubDate>Fri, 28 Jan 2022 14:00:00 +0000</pubDate>
      <link>https://dev.to/jdno/four-weeks-of-experiments-21a6</link>
      <guid>https://dev.to/jdno/four-weeks-of-experiments-21a6</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Lrquyhkx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1433840496881-cbd845929862%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDF8fHRlY2huaWNhbCUyMGRyYXdpbmd8ZW58MHx8fHwxNjQzMzU4MzIx%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Lrquyhkx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1433840496881-cbd845929862%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDF8fHRlY2huaWNhbCUyMGRyYXdpbmd8ZW58MHx8fHwxNjQzMzU4MzIx%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" alt="Four Weeks of Experiments" width="880" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the beginning of 2022, I set the goal to experiment with different project ideas and technologies. I want to learn new things and build something, and after four weeks it is time to pause and reflect on the progress.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Kind of New Year's Resolution
&lt;/h2&gt;

&lt;p&gt;Around the beginning of the new year, I reflected on what I had done in the past year and what I wanted to do next. I felt like my growth as a software engineer had stagnated a bit. I was experimenting with Rust, either building small open source tools or trying to learn game development. At work, I was using a mix of Java, TypeScript, and mostly Bash scripts. But neither in my personal time nor at work did I feel like I was making much progress.&lt;/p&gt;

&lt;p&gt;As a result, a goal for 2022 became to dedicate more time and focus to software development. Instead of only messing around with ideas, I want to push myself to actually "complete" one (assuming I can control the inevitable scope creep). I expect to learn from the process. Both in terms of "boring" work that I would typically try to avoid in my experiments, as well as in having something "in production" that I am solely responsible for.&lt;/p&gt;

&lt;p&gt;But I started the year without a good idea what to do. There are a handful of projects that I have started, stopped, and restarted more often than I can count. My idea for a &lt;a href="https://www.jdno.dev/why-i-want-to-build-a-video-game-for-programmers/"&gt;video game for programmers&lt;/a&gt; is one of those. But there are reasons why I eventually stopped working on them. Scope, feasibility, time and money. And I wasn't sure what kind of tech stack I wanted to explore. Stay with Rust, go back to backend development, or finally dive deep into React?&lt;/p&gt;

&lt;p&gt;So I decided to just jump in and see where the road would lead me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a GitHub App with Rust
&lt;/h2&gt;

&lt;p&gt;Developer tools have always excited me. Maybe that is because I like solving my own problems. One idea that I have been coming back to many times is figuring out a better way to keep template files in sync on GitHub. A lot of configuration files in my projects are identical, and I tend to improve them as I learn more. Maybe most notably, my GitHub Actions are constantly evolving as the platform matures. When I make changes in repository A, I want those changes to also be applied to repository B that uses the same tech stack. This is a problem that can be solved with a &lt;a href="https://docs.github.com/en/developers/apps"&gt;GitHub App&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So I started the year working on this idea. I was set on using Rust for the project. It only requires a simple web server to interface with GitHub, and then a bunch of business logic to run through the actual workflow of syncing the files. I had just bought the book &lt;a href="https://www.zero2prod.com"&gt;Zero to Production&lt;/a&gt;, and this was a great opportunity to implement its lessons. It was easy to get started, and the first few days were a lot of fun. I learned a ton by following the book, especially about areas like tracing and instrumentation that I wasn't yet familiar with.&lt;/p&gt;

&lt;p&gt;But towards the end of the week, doubts started to creep up. For one, I was implementing a very narrow workflow. But it still required a lot of code just to get started. Interfacing with GitHub's webhook, GitHub's API, and the Git object model all introduced unforeseen complexities. Because I had to do all this work anyways, I started thinking of broadening the scope. In the end, I had a grandious idea of an automation engine that provides a flow-based, no-code environment to automate arbitrary workflows. Think Zapier but for developers. I really like the idea, but it is too ambitious for the time I have. And I didn't like the idea of investing that much time to build something that fully depends on someone else's platform, in this case GitHub.&lt;/p&gt;

&lt;p&gt;You can read more about the first week in these devlogs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/jdno/day-1-an-empty-source-file-co5"&gt;Day 1 – An Empty Source File&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/jdno/day-2-exploring-an-idea-21nl"&gt;Day 2 – Exploring an Idea&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/jdno/day-3-productive-procrastination-39f"&gt;Day 3 – Productive Procrastination&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/jdno/day-4-adding-tech-debt-3on6"&gt;Day 4 – Adding Tech Debt&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Reflecting on this first week, I really liked the routine of journaling about the progress on the blog. Getting swept away by ever bigger dreams about an automation engine was fun as well. As was working with Rust. But the nagging feeling of building something that could become obsolete any day by a new feature of GitHub was frustrating.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a Desktop App with Rust
&lt;/h2&gt;

&lt;p&gt;The second week is a logical consequence of the first, as it took what I liked about week 1 and does the opposite for the rest. Instead of aiming to build an overly complex and ambitious enterprise, it started with the goal to create a desktop app. A well-defined scope, no operational responsibility, and privacy-focused by keeping data on the user's device. Since it was still the beginning of the year, my goal was to build an app that helps users set goals. I wanted to solve my own problem again.&lt;/p&gt;

&lt;p&gt;What I liked about week 1 was using Rust. And building a desktop app with Rust was a great excuse to check out two projects that I had been interested in for a long time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://tauri.studio/"&gt;Tauri&lt;/a&gt; is an alternative to &lt;a href="https://www.electronjs.org/"&gt;Electron&lt;/a&gt; and creates desktop apps from web frontends&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://yew.rs/"&gt;Yew&lt;/a&gt; is a framework to build web apps with Rust&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first two days were great and a lot of run again. I started with Yew, and really enjoyed playing with the framework. It takes a lot of inspiration from React, which feels quite intuitive. And it is still Rust, so you get all the benefits of the language. A strong type system, helpful compiler errors, and great developer tooling.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;yew&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;components&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;page&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;PageContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PageHeader&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Dashboard&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Component&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Dashboard&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Properties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;html!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"dashboard"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PageHeader&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Dashboard"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PageContent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"This is the dashboard's content."&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;PageContent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But figuring out how to adept Yew for a desktop app and make it work well with Tauri was a bit too much for me. Tauri does not have a Rust SDK, and officially only supports Node apps. And Yew is designed for the browser, not a Node runtime. So I got stuck trying to figure out a way to access the local file system so that I could save the user's data.&lt;/p&gt;

&lt;p&gt;I tried to work around this by embedding a web server in the Tauri app. The idea was to run a local web server that the web frontend could interact with, thus avoiding the need to access the file system from Yew. This approach also allowed me to go back to &lt;a href="https://www.zero2prod.com"&gt;Zero to Production&lt;/a&gt; and build a web server. But it made things way too complicated. It also didn't help that I wanted to use GraphQL. In the end, I had thousands of lines of boilerplate code just to get a simple form saved.&lt;/p&gt;

&lt;p&gt;Building a desktop app with Tauri and Yew just didn't feel feasible at this point in time. At least not with the knowledge that I had about both projects. And going back to my goals for 2022, I didn't feel that the experimentation I was doing was aligned with the goal of shipping something to production.&lt;/p&gt;

&lt;p&gt;Ironically, a week later a &lt;a href="https://dev.to/stevepryde/create-a-desktop-app-in-rust-using-tauri-and-yew-2bhe"&gt;blog post about building desktop apps with Tauri and Yew&lt;/a&gt; got published. It answered the questions that I had, and showed how to get past the problems that I was experiencing. But at that point I had already moved on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a (Deskop|Web) App with Next.js
&lt;/h2&gt;

&lt;p&gt;The next iteration was an attempt to replace Yew with &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt;. Next.js is a framework that I always wanted to try out, and it seemed logical at first to switch from Rust to Node. I would still be using a component-based framework, but with better support for Tauri.&lt;/p&gt;

&lt;p&gt;I quickly remembered why I didn't like working with the Node ecosystem. Getting started with Next.js was easy, but soon enough I ran into the first problems. The testing framework didn't play nicely with the way that assets got imported. Tauri's NPM package wasn't compatible with the default Webpack setup (due to the use of ES modules). I probably spent more time debugging these issues than writing code.&lt;/p&gt;

&lt;p&gt;More fundamentally, however, I realized that Next.js is not the right framework for desktop apps. It is designed for web applications, offering features such as &lt;a href="https://nextjs.org/docs/basic-features/pages#pre-rendering"&gt;server-side rendering&lt;/a&gt; and &lt;a href="https://nextjs.org/docs/api-routes/introduction"&gt;a way to build APIs&lt;/a&gt;. I am truly impressed by the framework, but it simply wasn't the right tool for the job.&lt;/p&gt;

&lt;p&gt;I switched to React next, and spend a day or two experimenting with that approach. But when it came to saving data, I still ran into the build issues with Tauri and the question how to interact with the file system. I was ready to abandon the idea of building a desktop app. If I were to build a web app, I could use Next.js again. But how would I store data? Privacy is important to me, and I didn't want to just throw everything into Firebase or any other backend-as-a-service.&lt;/p&gt;

&lt;p&gt;So I not only abandoned the idea of building a desktop app, I also abandoned the idea of using a frontend framework for the job.&lt;/p&gt;

&lt;p&gt;In hindsight, this was probably the most frustrating experience of the month. I always have high hopes when I start working with TypeScript. But every time there are issues. Compared to the developer experience that I have with Rust or before that Ruby, I simply feel unproductive and mostly fighting the tools. Maybe that would change after a while, but I never get to the point because it's just too annoying.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a Web App with Rails
&lt;/h2&gt;

&lt;p&gt;In a past life, I worked as a Ruby on Rails developer. I love the framework and the productivity it enables. And in December 2021, &lt;a href="https://rubyonrails.org/2021/12/15/Rails-7-fulfilling-a-vision"&gt;Rails 7 was released&lt;/a&gt; with a bunch of exciting new features. &lt;a href="https://hotwired.dev/"&gt;Hotwire&lt;/a&gt; is now the default solution for frontend development, combining the responsiveness of single-page applications with the benefits of server-side rendering. And &lt;a href="https://guides.rubyonrails.org/active_record_encryption.html"&gt;Active Record Encryption&lt;/a&gt; makes it easy to protect sensitive data in an application. It checked all the requirements that I had after experimenting with React and TypeScript.&lt;/p&gt;

&lt;p&gt;So in week 4–this week–I spun up a new development environment for a Rails app. The goal was still to build a tool for personal goal setting. But a web app enabled a few exciting features that would've been very difficult to add to a desktop app. The app can send notifications much easier, for example when a user hasn't updated their progress in a while. It is also possible to access the app from different devices, allowing users to check in whenever they want.&lt;/p&gt;

&lt;p&gt;Progress during the week was slow, though. Other things required my attention, and I wasn't able to focus much on the project. I was also reminded of why I wanted to build a desktop app in the first place. Storing the user's data on the central server requires so much thought about security, privacy, and current regulations. I am not yet convinced that this is the direction that I want to take.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reflecting on Four Experiments
&lt;/h2&gt;

&lt;p&gt;In four weeks, I tried four different approaches of building a product. It started with a web service, radically pivoted to a desktop app, and from there evolved to the point where it became a web app again.&lt;/p&gt;

&lt;p&gt;More than anything else, I am frustrated with my progress. At the beginning of the month, I thought that I would be working on one idea the whole time. And I expected to have a prototype in production after four weeks. But I feel very far away from that goal right now.&lt;/p&gt;

&lt;p&gt;I am happy with the experimentation, though. The automation engine wasn't a good idea to pursue. It was too complex, too ambitious, and it would've taken months to get even a prototype out of the door. But I like the idea of the personal goal setting app, because I am passionate about the topic and it is very well scoped. Without experimentation, I wouldn't have ended up here.&lt;/p&gt;

&lt;p&gt;I also have to acknowledge that I didn't know enough about building desktop apps at the beginning of the month. Only by trying and failing did I start to dig deeper into the topic. After I finish this post, I will spend the rest of the day reading the paper &lt;a href="https://www.inkandswitch.com/local-first"&gt;Local-first software&lt;/a&gt; about "a set of principles for software that enables both collaboration &lt;em&gt;and&lt;/em&gt; ownership for users". Maybe that will change my goals for next month again, but I will have learned about an interesting new idea no matter what happens.&lt;/p&gt;

&lt;p&gt;So I shouldn't feel frustrated with the progress. I did learn a lot and got to try a a bunch of frameworks that were on my to-do-list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Process Over Outcome
&lt;/h2&gt;

&lt;p&gt;I actually start to think that I am not frustrated with the outcome, but with my process during the month.&lt;/p&gt;

&lt;p&gt;A goal of mine was to establish a routine, and I definitely failed to do that. As mentioned in the beginning for example, I really liked writing short(er) blog posts that reflected on the day. But I stopped doing that after the first week. I also wanted to relaunch my podcast, which I haven't done yet. And I wanted to try live-coding on Twitch, which also didn't happen. I set out with an idea for how I want to work, and I failed to follow through on that.&lt;/p&gt;

&lt;p&gt;So looking forward to the next months, I want to focus on the process more than on the outcomes.&lt;/p&gt;

&lt;p&gt;One aspect of that is certainly to set intentions again. I want to set a goal for the week and then for each day, and check that I am on track towards those goals. Writing a short blog post at the beginning in the morning was definitely helpful in establishing a goal for that day. But it is also a lot of overhead, so I'll have to experiment and see what formats works. Maybe setting the goal is better done by creating tasks in OmniFocus, and then reflecting on the week in a blog post just like this one. I am also considering adopting the &lt;a href="https://basecamp.com/shapeup"&gt;Shape Up&lt;/a&gt; methodology to plan a week ahead and then focus on execution during the week. I will have to experiment with this and see what works best for me.&lt;/p&gt;

&lt;p&gt;This blog post is now a reflection of the whole month, and I feel that time is too long. A weekly or bi-weekly interval would be better suited to spot trends and react in time. There were multiple moments where I could've stopped and reflected on how things were going during the past month. That would've allowed me to react earlier, and possible avoid the feeling of frustration that I feel now.&lt;/p&gt;

&lt;p&gt;A week as a unit for planning and reflection, and then days with a certain routine feel like the most promising approach. I do have to be mindful of my other responsibilities, though. I can make plans for my side project, but there will be days were I just won't have the time to work on it.&lt;/p&gt;

&lt;p&gt;So let's try to enjoy the process and focus less on outcomes.&lt;/p&gt;

</description>
      <category>devlog</category>
    </item>
    <item>
      <title>Day 4 – Adding Tech Debt</title>
      <dc:creator>Jan David</dc:creator>
      <pubDate>Thu, 06 Jan 2022 22:00:00 +0000</pubDate>
      <link>https://dev.to/jdno/day-4-adding-tech-debt-3on6</link>
      <guid>https://dev.to/jdno/day-4-adding-tech-debt-3on6</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VJgilBUs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1452960962994-acf4fd70b632%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDE4fHxxdWV1ZXxlbnwwfHx8fDE2NDE1MDI1MTA%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VJgilBUs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1452960962994-acf4fd70b632%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDE4fHxxdWV1ZXxlbnwwfHx8fDE2NDE1MDI1MTA%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" alt="Day 4 – Adding Tech Debt" width="880" height="584"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jdno/day-3-productive-procrastination-39f"&gt;Yesterday&lt;/a&gt;, I was following along with the book &lt;a href="https://www.zero2prod.com"&gt;Zero to Production&lt;/a&gt; to set up a web server in Rust. Today, I went rogue and added a background job system. All code quality metrics have dropped as a result. 😅&lt;/p&gt;

&lt;h2&gt;
  
  
  Queuing Work for Later
&lt;/h2&gt;

&lt;p&gt;When I was working as a Ruby on Rails developer a few years ago, it was common practice to queue jobs for later. The motivation for this was simple: Keep the HTTP request cycle as short as possible. Complex tasks and work that could be done asynchronously was pushed into a job queue. One reasons for this was that it improved the user experience. Another that &lt;a href="https://sidekiq.org/"&gt;Sidekiq&lt;/a&gt;, the background job system, was just so good and reliable. And when a job failed due to a bug, it was possible to fix the bug and try again.&lt;/p&gt;

&lt;p&gt;Maybe it is a premature optimization, but I am approaching my current project in the same way. Incoming webhooks get serialized and pushed into a queue for later processing. A background worker dequeues the events and checks if more work needs to be done. If so, it can either create more jobs in the queue or perform the work itself.&lt;/p&gt;

&lt;p&gt;The reason that I like this design is that it creates flexibility and resiliency. First of all, the background worker does not have any time constraints. If the web server were to perform the work, the HTTP request might time out while it was busy. This makes it possible to choose less performant, but more maintainable algorithms. For example, work can be done in sequence instead of in parallel. This avoid a while group of concurrency issues that can occur when parallelizing data access. Second, if something fails it can easily be retried. This is particularly useful if the work requires interfacing with third-party systems. These systems might be unavailable, in which case the job can simply be retried at a later time. And sometimes we make mistakes. When a job fails due to a bug, it is still in the queue. A developer can fix the bug, deploy a new version of the application, and the job can succeed.&lt;/p&gt;

&lt;p&gt;The downside of this approach is of course that it requires a background job system and a worker. Thus more moving pieces and more orchestration. But I have had great experiences with &lt;a href="https://sidekiq.org/"&gt;Sidekiq&lt;/a&gt;, and I am sure that its polyglot brother &lt;a href="https://contribsys.com/faktory/"&gt;Faktory&lt;/a&gt; will work just as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decreasing Code Quality
&lt;/h2&gt;

&lt;p&gt;When I was working on the web server yesterday, I had the advantage of following along with the book &lt;a href="https://www.zero2prod.com"&gt;Zero to Production&lt;/a&gt; by Luca Palmieri. The book provided a reference implementation for many common patterns, for example integration tests and obversability. As someone who is building their first web application in Rust, I appreciate the guidance.&lt;/p&gt;

&lt;p&gt;Today, I went off the beaten path to set up the background job system. This had two particular challenges:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Finding the right abstraction for the background jobs&lt;/li&gt;
&lt;li&gt;Mocking the job system in integration tests&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I probably spent most of my time dabbling with the interface between the web server and the background worker. The simplest solution would have been to throw the whole webhook into the queue. The benefit of this approach would have been that it kept the web server very simple. But it would have forced the background worker to know implementation details about GitHub's webhooks. This felt like tech debt to me.&lt;/p&gt;

&lt;p&gt;So instead, the web server deserializes the incoming webhook and extracts the necessary information from it. It creates an &lt;code&gt;Event&lt;/code&gt; object and pushes it into the queue. This keeps the implementation details of GitHub's webhook events in a single place. And it makes it easier to support other platforms in the future, since the core library does not need to be changed for that. Instead, it is enough to add a new endpoint that can deserialize–for example–GitLab's webhooks.&lt;/p&gt;

&lt;p&gt;The code is still a mess. There is considerable overlap between the core library and the web server. A quick search reveals that there are roughly 8-12 types that deal with pull request events. There is the &lt;code&gt;PullRequestWebhook&lt;/code&gt; from GitHub, and then the &lt;code&gt;PullRequestEvent&lt;/code&gt; that is used internally. Both have similar, but still different fields. While I don't like the duplication, changing the internal types to work with GitHub's data structures felt even more wrong.&lt;/p&gt;

&lt;p&gt;My hope is that this will improve over time and as I become more proficient with Rust and GitHub's API. Right now, I have only implemented a single event type. Once there are more, patterns might start to emerge that make it obvious how to clean up the code. But the code works, and that is the most important thing for today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;The next step is obviously to create the background worker. But this will have to wait until next week. The routine that I am trying in January is to work four days on the code itself. The fifth day will be spent on &lt;a href="https://basecamp.com/shapeup"&gt;shaping&lt;/a&gt; the next week. I also want to start recording my personal podcast again, and leave time to write technical blog posts. My hypothesis is that a day of reflecting and planning will make the other four days much more productive and valuable.&lt;/p&gt;

&lt;p&gt;If you are interested, here is the first episode from my podcast, recorded last year. You can subscribe to it on iTunes, Spotify, Overcast, and pretty much everywhere else.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://open.spotify.com/embed/episode/5ROz165f5MXXKEJBDtXqaJ" width="100%" height="232px"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>devlog</category>
      <category>rust</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Day 3 – Productive Procrastination</title>
      <dc:creator>Jan David</dc:creator>
      <pubDate>Wed, 05 Jan 2022 21:00:00 +0000</pubDate>
      <link>https://dev.to/jdno/day-3-productive-procrastination-39f</link>
      <guid>https://dev.to/jdno/day-3-productive-procrastination-39f</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1587654780291-39c9404d746b%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDN8fGxlZ298ZW58MHx8fHwxNjQxNDEyOTQz%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1587654780291-39c9404d746b%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDN8fGxlZ298ZW58MHx8fHwxNjQxNDEyOTQz%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" alt="Day 3 – Productive Procrastination"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After two days of mostly theoretical work, I felt like writing some code today. So I got my copy of the book &lt;a href="https://www.zero2prod.com" rel="noopener noreferrer"&gt;Zero to Production&lt;/a&gt; and worked on the app's web server. As a result, the project is built with Rust now...&lt;/p&gt;

&lt;h2&gt;
  
  
  Subscribing to Events from GitHub
&lt;/h2&gt;

&lt;p&gt;I wrote about what a minimum viable product for this project would look like in &lt;a href="https://dev.to/jdno/day-2-exploring-an-idea-21nl"&gt;yesterday's post&lt;/a&gt;. One of the features that it needs is the ability to receive events from code hosting providers like GitHub. This feature has a simple and a complicated part.&lt;/p&gt;

&lt;p&gt;The simple part is how platforms like GitHub deliver these events. Whenever something happens on GitHub, a webhook event is sent to any app that is subscribed to it. In the case of GitHub, this is done for (almost) literally &lt;a href="https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads" rel="noopener noreferrer"&gt;everything&lt;/a&gt;. The webhook is sent to a pre-configured URL, which means the app needs a web server that can receive them.&lt;/p&gt;

&lt;p&gt;The complicated part is figuring out what to do with the event. For this project, it means figuring out if any workflows need to run. This requires reading the user's configuration, which has been a topic of &lt;a href="https://dev.to/jdno/day-2-exploring-an-idea-21nl"&gt;yesterday's post&lt;/a&gt; as well. Not much has changed since then, and how the configuration will look has yet to be decided.&lt;/p&gt;

&lt;p&gt;So I decided to focus on the simple part that is clearly scoped for today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Zero to Production
&lt;/h2&gt;

&lt;p&gt;Last year, I bought a copy of the book &lt;a href="https://www.zero2prod.com" rel="noopener noreferrer"&gt;Zero to Production&lt;/a&gt; by Luca Palmieri. It describes how to build a production-grade backend server with &lt;a href="https://rust-lang.org" rel="noopener noreferrer"&gt;Rust&lt;/a&gt;. Back then I was working on a similar–albeit more limited–idea, and read through the first chapter as I was experimenting with the idea. I learned a lot from it, and always wanted to finish the book. As luck would have it, an update just dropped and I picked up the latest version and got started...&lt;/p&gt;

&lt;p&gt;The book uses an iterative approach to introduce new topics. You start by setting up the web framework. Then you add integration tests, and after that a database. Each chapter builds on the previous one, and there is a strong focus on having something working after each step.&lt;/p&gt;

&lt;h2&gt;
  
  
  +2,532 −1
&lt;/h2&gt;

&lt;p&gt;After working through the first four chapters of the book, I reached a good stopping point for today. I have a web server now that can receive webhooks from GitHub. The server verifies the authenticity of the webhooks by checking their cryptographic signature. Everything is tested with integration tests. And instrumentation is in place to monitor the server once it gets deployed. A lot of code was added today.&lt;/p&gt;

&lt;p&gt;The next step is putting the events in a queue so that they can be processed in the background. This requires figuring out what data is later needed to process the events. And it needs setting up a background job system.&lt;/p&gt;

&lt;p&gt;When I worked as a &lt;a href="https://rubyonrails.org/" rel="noopener noreferrer"&gt;Ruby on Rails&lt;/a&gt; developer in the past, I always had great experiences with &lt;a href="https://sidekiq.org/" rel="noopener noreferrer"&gt;Sidekiq&lt;/a&gt;. It was so good that it became second nature to throw everything that didn't need to be synchronous into a queue and process it in the background. Luckily, &lt;a href="https://contribsys.com/faktory/" rel="noopener noreferrer"&gt;Faktory&lt;/a&gt; exists as a "polyglot version of Sidekiq" (don't @ me).&lt;/p&gt;

&lt;p&gt;My goal for tomorrow is to integrate Faktory into the app, and throw incoming webhooks into a queue. A background worker can then pick them up and figure out what to do for the event. This last step will require figuring out how to store configuration, but that's a problem for another day...&lt;/p&gt;

&lt;p&gt;Day 3 was fun, let's continue tomorrow!&lt;/p&gt;

</description>
      <category>devlog</category>
      <category>rust</category>
    </item>
    <item>
      <title>Day 2 – Exploring an Idea</title>
      <dc:creator>Jan David</dc:creator>
      <pubDate>Tue, 04 Jan 2022 14:00:00 +0000</pubDate>
      <link>https://dev.to/jdno/day-2-exploring-an-idea-21nl</link>
      <guid>https://dev.to/jdno/day-2-exploring-an-idea-21nl</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ODY4XoBe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1542621334-a254cf47733d%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDF8fGJsdWVwcmludHxlbnwwfHx8fDE2NDEyOTQ5NTU%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ODY4XoBe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1542621334-a254cf47733d%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDF8fGJsdWVwcmludHxlbnwwfHx8fDE2NDEyOTQ5NTU%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" alt="Day 2 – Exploring an Idea" width="880" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/jdno/day-1-an-empty-source-file-co5"&gt;Yesterday&lt;/a&gt;, I brainstormed ideas for a project that I can build in a few weeks. Today, I am exploring one of those ideas in more depth. The goal is to develop a better understanding of the product and its constraints.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automation for Git Repositories
&lt;/h2&gt;

&lt;p&gt;When I look at my own (open source) work, how I use Git repositories has changed dramatically over the past two years.&lt;/p&gt;

&lt;p&gt;In the past, a repository was simply a place for source code. It was one of many tools used to organize a project. But with GitHub, more and more functionality moved into a central place. Now a repository is also the home of issues, discussions, and even the project's website.&lt;/p&gt;

&lt;p&gt;Additionally, configuration-as-code has been a growing trend. And these configurations have moved into the repository as well. Pipelines for continuous integration. Deployment configurations for Heroku or other platforms. Configuration for a wide variety of bots that automate development tasks.&lt;/p&gt;

&lt;p&gt;What I find myself with is thus a growing number of repositories, each with more and more configuration files. As someone who values consistency and a great developer experience, I want these to be up-to-date. When I learn how to improve my CI in one project, I want to update every other project as well.&lt;/p&gt;

&lt;p&gt;I started to think about this problem as templates that I want to keep up-to-date. But while toying with the idea, I noticed that this is actually just a concrete implementation of a generic algorithm. What I really want is to take an action based on a trigger. So when a file is updated in one repository (the &lt;em&gt;trigger&lt;/em&gt;), I want to copy it to another (the &lt;em&gt;action&lt;/em&gt;). Some actions I only want to perform sometimes, which I can control through a &lt;em&gt;condition&lt;/em&gt;. For example, only perform the action when the default branch is updated.&lt;/p&gt;

&lt;p&gt;What I want to build over the next few weeks is a service that can do that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features of a Prototype
&lt;/h2&gt;

&lt;p&gt;Given that time is limited, I want to be strategic in the design and implementation of the product. There are a lot of things that I &lt;em&gt;can&lt;/em&gt; do, but what is it that I &lt;em&gt;need&lt;/em&gt; to do?&lt;/p&gt;

&lt;p&gt;For a functional product, at least the following features must work:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Allow users to configure workflows&lt;/li&gt;
&lt;li&gt;Subscribe to events from platforms like GitHub&lt;/li&gt;
&lt;li&gt;Execute workflows when their conditions are met&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each of these have varying levels of complexity based on the implementation. For example, it would be great to have a graphical user interface to configure the workflow. But then again, it is also possible to define the workflow in a configuration file. The latter can be build in much less time, and is thus probably a better solution for this stage.&lt;/p&gt;

&lt;p&gt;Besides these functional requirements, there are also non-functional requirements. One category of those are restrictions and recommendations imposed by the platforms. GitHub, for example, provides a few &lt;a href="https://probot.github.io"&gt;best practices&lt;/a&gt; with its &lt;a href="https://probot.github.io"&gt;Probot&lt;/a&gt; framework. One of them is to keep the configuration as code in the repository whenever possible. These also need to be considered when designing the features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features of a Future Product
&lt;/h2&gt;

&lt;p&gt;While I am limited in what I can build now, I still want to consider what the product could look like in the far future. I have to be careful not to fall into the trap of premature optimization, though. I want the vision to guide my design, without forcing me into a product that is too complex for the current moment.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://dev.to/jdno/day-1-an-empty-source-file-co5"&gt;yesterday's post&lt;/a&gt;, I mentioned that I see two long-term futures for this project. The first is open sourcing the project once I am done or running out of time. The second is offering the product as a service so that I can learn more about business as well. While there are some differences, they share a lot of common features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Self-hosting
&lt;/h3&gt;

&lt;p&gt;Allowing the users to run the software themselves is an important feature for both an open source or a commercial product. Given the nature of the tool, it requires far-reaching access to source code. This might be an acceptable risk for open source or side projects. But others might want to run the software themselves to ensure only they have access to their code.&lt;/p&gt;

&lt;p&gt;Self-hosting limits how the application can be built. A monolith is better than a complex microservice architecture. A widely available database like PostgreSQL better than vendor-dependent solutions like DynamoDB. Both make it easier for someone else to pick up the product and deploy it to their own infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Graphical User Interface
&lt;/h3&gt;

&lt;p&gt;A graphical user interface can greatly improve the configuration of the software. It shortens the feedback loop, and can highlight information when it is relevant to the user. For example, validations can catch mistakes in real-time. The user no longer has to wait for the software to run and report an issue. And the UI can surface features that the user might not even know existed.&lt;/p&gt;

&lt;p&gt;A UI also makes it possible to manage workflows across repositories. Instead of having to copy configuration files, a user can simply click a button to add or remove a workflow from a repository. When viewing a workflow, a user can quickly see where it is being used. This is especially valuable for larger organizations with many repositories.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Scripts
&lt;/h3&gt;

&lt;p&gt;Triggers, conditions, and actions will probably be hard-coded in the first version of the product. Users can combine them in workflows, but they cannot define their own. This should be fine for most projects, but power users will run into limitations. Since this is a product for developers, it is only logical to allow them to create their own actions.&lt;/p&gt;

&lt;p&gt;How to execute custom code in a safe and responsible way, I don't know. This makes this a feature for later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Most of the requirements and constraints don't matter for the technical architecture. The idea is generic enough that it can be implemented with any web framework, be it in Ruby, Rust, or Node. Some things will be easier in one tool compared to the others, but overall it balances out.&lt;/p&gt;

&lt;p&gt;To me, the biggest challenge is building a secure product that follows the platform guidelines.&lt;/p&gt;

&lt;p&gt;On GitHub, for example, it is convention to have the configuration as code in the repository. This works well for workflows that only touch a single repository. But what about organization-wide automation? Where does their configuration go?&lt;/p&gt;

&lt;p&gt;Another concern is honoring access controls. A company might use code reviews to enforce the four-eyes principle. What does this mean for workflows that are created outside of GitHub or GitLab? Do they need to be reviewed as well? Does every execution of a workflow need to be reviewed?&lt;/p&gt;

&lt;p&gt;These are far more challenging questions than the technical implementation. These kinds of questions are probably the reason we have so much configuration-as-code now. Adding a workflow to the configuration file automatically follows the same process as any other code change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Goals for Today
&lt;/h2&gt;

&lt;p&gt;I will be spending the rest of the day thinking about the questions above. Configuration-as-code seems like absolutely the right path for a variety of reasons. But the whole project was started because managing files across repositories is painful. So how would a good user experience look like?&lt;/p&gt;

&lt;p&gt;There are two ideas specifically that I want to explore. The first is centralizing the configuration somewhere, for example in a dedicated repository. The other using the automation I am building to also manage the configuration.&lt;/p&gt;

&lt;p&gt;Day 2 will be a tough one.&lt;/p&gt;

</description>
      <category>devlog</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Day 1 – An Empty Source File</title>
      <dc:creator>Jan David</dc:creator>
      <pubDate>Mon, 03 Jan 2022 12:00:00 +0000</pubDate>
      <link>https://dev.to/jdno/day-1-an-empty-source-file-co5</link>
      <guid>https://dev.to/jdno/day-1-an-empty-source-file-co5</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fepvr7jfh0gntv78rmlss.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fepvr7jfh0gntv78rmlss.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The new year is here and I have some time to experiment. It has been a while since I had the opportunity to explore new technologies and build something. I have a few ideas what to do and what to learn, but I still need to figure out the details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Criteria for a New Project
&lt;/h2&gt;

&lt;p&gt;I have been thinking a lot about the problems that excite me while brainstorming what I want to build. As a software developer, I like building products for other developers. It's a space I know well, and I enjoy designing good developer experiences.&lt;/p&gt;

&lt;p&gt;A topic that has interested me for years, but which I haven't pursued in a while, is entrepreneurship. As I am thinking about problems, I want to make sure that any solution has the potential to be monetized. This would allow me to learn some totally new skills, and help me maintain the project for a longer time. Maybe even full-time. 🤞&lt;/p&gt;

&lt;p&gt;On a technical level, I am excited about Rust and I want to learn React. I have worked mostly as a backend and DevOps developer, and am interested in practicing frontend development. As a former Rails developer, I am also very curious about the changes that landed in Rails 6 and 7.&lt;/p&gt;

&lt;p&gt;The biggest challenge for me is keeping the scope small. The ideas I have tend to grow into very ambitious projects that would need months of not years to fully realize. I often lose interest in the projects before they are finished, because it takes too long to see any value. I have zero doubts that I will make the same mistake again, though.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three Project Ideas
&lt;/h2&gt;

&lt;p&gt;In the past years, I have been exploring three different ideas with varying degrees of success. But I have been coming back to all of them, because there is something about them that intrigues me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automation for Git Repositories
&lt;/h3&gt;

&lt;p&gt;An idea that I have been working on one-and-off for a while now is automating certain tasks in a Git repository. Specifically, I want an easy way to maintain templates for configuration files, CI workflows, and other developer tooling. Whenever I update one of them, I want the file to be updated in all repositories automatically.&lt;/p&gt;

&lt;p&gt;There is some prior art that implements this on GitHub using &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;Actions&lt;/a&gt;, but copying files between repositories with Actions feels awkward for various reasons. A &lt;a href="https://docs.github.com/en/developers/apps" rel="noopener noreferrer"&gt;GitHub App&lt;/a&gt; would provide a much better user experience.&lt;/p&gt;

&lt;p&gt;I am doubtful that this feature alone would be enough for a convincing value proposition. But while playing with the idea, I noticed that it is possible to abstract it into a more general concept. What I want to do is catch a trigger (a file has been updated), check one or more conditions (on the default branch?), and then perform an action (copy the file to another repository). This loop of trigger, condition, and action can be used for other workflows as well. For example, auto-merging pull requests or closing issues when certain conditions are met.&lt;/p&gt;

&lt;h3&gt;
  
  
  Desktop App for File Management
&lt;/h3&gt;

&lt;p&gt;Every year I have to file taxes, and every year I am missing some documents that I need to do so. And I have some anxiety that I am not archiving important documents for the future. Who knows what I need to have ready in 60 years to get my pension?&lt;/p&gt;

&lt;p&gt;The second idea is thus an app that helps organize files on the local machine. The idea is quite simple: A directory is a &lt;em&gt;library&lt;/em&gt; with many &lt;em&gt;indicies&lt;/em&gt;. When a document is added to the library, it is copied into an archive and then linked into every index. Each index has rules that organize the documents in it. For example, one index might sort files by year and another by file type. This might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;library
├── .archive
│   └── day-1.md
├── by type
│   └── md
│       └── day-1.md
└── by year
    └── 2022
        └── day-1.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a project that is ideally suited for a CLI in Rust, maybe with a React-based desktop app that calls either the CLI or a shared library.&lt;/p&gt;

&lt;p&gt;There are also some interesting features that could help users manage their files. For example, identifying documents that are added on a regular cadence such as payslips, and warning the user if any are missing. But even with such features, I am again very doubtful about the value proposition and the ability to monetizate the app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Videogame for Programmers
&lt;/h3&gt;

&lt;p&gt;I have been writing about this idea a bunch last year, but none of my experiments came to fruition yet. Either the scope was too big, the architecture too complex, or probably both.&lt;/p&gt;

&lt;p&gt;It is again a simple idea: I like programming, but miss more engaging ways to learn new concepts or programming languages. I don't like doing courses, because they are often aimed at beginners (I don't need yet another introduction to variables and functions). At the same time, I also enjoy videogames and admire the feedback loops they have. Putting both together, I think it could be great fun to have sandbox-style games with which players can practice programming.&lt;/p&gt;

&lt;p&gt;What has been challenging in the past is creating a nice API for players that integrates well with the engine running the game. As a novice to game development, there are just too many unknowns to hit the nail on the head on the first try. I would have to build a few small games to learn, but those cannot be monetized. Even worse, the market is very saturated and monetizing games is difficult enough as it is.&lt;/p&gt;

&lt;h3&gt;
  
  
  Others
&lt;/h3&gt;

&lt;p&gt;There are more ideas that I thought about or for which I registered domains and created repositories. But many of them are related to one of the three projects above, and can only be great if they are extracted from them.&lt;/p&gt;

&lt;p&gt;For example, a &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;GitHub Action&lt;/a&gt; that can easily be customized to validate configuration files. I want to have this functionality every time that I think about creating either a GitHub Action or a GitHub App. But without having something in production to validate the value proposition, it is way too easy to build something that doesn't solve an actual issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I am leaning towards working on the Git automation idea. I know the problem from first-hand experience, and am fairly confident in the proposed solution. And judging by the amount of GitHub Actions in the marketplace that automate workflows, I am confident that this is a valuable problem to solve.&lt;/p&gt;

&lt;p&gt;The runner-up is the video game for programmers. It is a passion project of mine, and I would love for it to exist. But I am afraid that my ambition far exceeds my skills, and that is is not possible for me to make meaningful progress in the time that I have.&lt;/p&gt;

&lt;h2&gt;
  
  
  Goals for Today
&lt;/h2&gt;

&lt;p&gt;The task for the rest of the day is to scope the automation project. The goal is to develop a rough plan for both the technical implementation and the project milestones, and look for any red flags or unknowns that could stop the project. I also want to think about the long-term vision for the project, since it will impact some of the technology decisions.&lt;/p&gt;

&lt;p&gt;At the end of the day, I want to have an initial draft for the architecture of the app and a rough outline of the milestones for the coming days.&lt;/p&gt;

&lt;p&gt;Day 1, let's go! See you again on day 2.&lt;/p&gt;

</description>
      <category>devlog</category>
      <category>webdev</category>
    </item>
    <item>
      <title>godot-logger – A Rust Logger for Godot</title>
      <dc:creator>Jan David</dc:creator>
      <pubDate>Wed, 20 Oct 2021 19:30:00 +0000</pubDate>
      <link>https://dev.to/jdno/godot-logger-a-rust-logger-for-godot-2fi9</link>
      <guid>https://dev.to/jdno/godot-logger-a-rust-logger-for-godot-2fi9</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--844TAAtx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2021/10/godot-logger.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--844TAAtx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2021/10/godot-logger.png" alt="godot-logger – A Rust Logger for Godot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jdno/godot-logger"&gt;godot-logger&lt;/a&gt; is a crate that complements the &lt;a href="https://godot-rust.github.io"&gt;godot-rust&lt;/a&gt; bindings for Godot, and prints logs to Godot's output console using the &lt;code&gt;godot_print!&lt;/code&gt; and &lt;code&gt;godot_warn!&lt;/code&gt; macros. It is available as open source on &lt;a href="https://github.com/jdno/godot-logger"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://godotengine.org/"&gt;Godot&lt;/a&gt; is an open source game engine with a powerful editor, tools to debug and profile the game, and support for many different programming langauges. Building games with &lt;a href="https://www.rust-lang.org/"&gt;Rust&lt;/a&gt; is possible thanks to the &lt;a href="https://godot-rust.github.io"&gt;godot-rust&lt;/a&gt; library, which provides bindings to Godot's API as well as a few convenience methods.&lt;/p&gt;

&lt;p&gt;One of the debugging tools inside &lt;a href="https://godotengine.org/"&gt;Godot&lt;/a&gt; is the output console. It prints information about the execution of the game, as well as log messages that have been placed in the code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--barJ4znD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2021/10/godot-output.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--barJ4znD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2021/10/godot-output.png" alt="godot-logger – A Rust Logger for Godot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://godot-rust.github.io"&gt;godot-rust&lt;/a&gt; provides two macros to write to the output console: &lt;code&gt;godot_print!&lt;/code&gt; and &lt;code&gt;godot_warn!&lt;/code&gt;. These can be called anywhere in the code, and will print the given message to the console.&lt;/p&gt;

&lt;p&gt;The problem that I encountered while working on my game was that these macros do not capture logs from third-party Rust libraries. It is very common for libraries in Rust to use the &lt;a href="https://crates.io/crates/log"&gt;log&lt;/a&gt; crate and its logging facade to define log statements in their code. These messages can then be printing by initializing a logger such as &lt;a href="https://crates.io/crates/env_logger"&gt;env_logger&lt;/a&gt; or &lt;a href="https://crates.io/crates/log4rs"&gt;log4rs&lt;/a&gt;. I wanted to see what the libraries in my project were doing, and I wanted to see the logs inside Godot's editor where I was running the game. After searching for an existing library and coming up empty, I decided to implement a logger myself that would print to Godot's output console.&lt;/p&gt;

&lt;h1&gt;
  
  
  Usage
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/jdno/godot-logger"&gt;godot-logger&lt;/a&gt; is very similar to popular logging frameworks such as &lt;a href="https://crates.io/crates/env_logger"&gt;env_logger&lt;/a&gt; or &lt;a href="https://crates.io/crates/log4rs"&gt;log4rs&lt;/a&gt;. It integrates with the logging facade of the &lt;a href="https://crates.io/crates/log"&gt;log&lt;/a&gt; crate, and prints log statements to Godot's output console.&lt;/p&gt;

&lt;p&gt;The simplest way to use &lt;a href="https://github.com/jdno/godot-logger"&gt;godot-logger&lt;/a&gt; is to add it and the &lt;a href="https://crates.io/crates/log"&gt;log&lt;/a&gt; crate as dependencies to your project's &lt;code&gt;Cargo.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[dependencies]
godot-logger = "1.0"
log = "0.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then configure and initialize the logger in the same method that is passed to &lt;code&gt;godot_init!&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use gdnative::prelude::*;
use godot_logger::GodotLogger;
use log::{Level, LevelFilter};

fn init(handle: InitHandle) {
    GodotLogger::builder()
        .default_log_level(Level::Info)
        .add_filter("godot_logger", LevelFilter::Debug)
        .init();
    log::debug!("Initialized the logger");
}

godot_init!(init);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example shows the configuration options that &lt;a href="https://github.com/jdno/godot-logger"&gt;godot-logger&lt;/a&gt; provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The default log level of &lt;code&gt;GodotLogger&lt;/code&gt; is &lt;code&gt;Level::Warn&lt;/code&gt;, but this can be changed with &lt;code&gt;default_log_level&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Module-specific log levels that take precedence over the default log level can be set by adding filters to the logger. A filter combines a &lt;a href="https://doc.rust-lang.org/book/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html"&gt;module path&lt;/a&gt; and a level filter, which makes it possible to very granularly control what gets logged.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The example above will print the following line to the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2021-10-20 20:00:00 DEBUG godot_logger Initialized the logger
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Below is a screenshot from my own project, which runs an embedded server built with &lt;a href="https://bevyengine.org"&gt;Bevy&lt;/a&gt; and has its code split across a few different crates ( &lt;code&gt;aomos&lt;/code&gt; namespace). As you can see, &lt;code&gt;log&lt;/code&gt; statements in these libraries are picked up and printed inside &lt;a href="https://godotengine.org/"&gt;Godot&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jRhjeVSP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2021/10/godot-logger-output-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jRhjeVSP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jdno.dev/content/images/2021/10/godot-logger-output-1.png" alt="godot-logger – A Rust Logger for Godot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Contributing
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/jdno/godot-logger"&gt;godot-logger&lt;/a&gt; is published as an open source project on &lt;a href="https://github.com/jdno/godot-logger"&gt;GitHub&lt;/a&gt;, and bug reports are always welcome.&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>opensource</category>
      <category>rust</category>
      <category>godot</category>
    </item>
    <item>
      <title>Hacktoberfest '21</title>
      <dc:creator>Jan David</dc:creator>
      <pubDate>Sat, 02 Oct 2021 14:26:23 +0000</pubDate>
      <link>https://dev.to/jdno/hacktoberfest-21-3blf</link>
      <guid>https://dev.to/jdno/hacktoberfest-21-3blf</guid>
      <description>&lt;p&gt;&lt;a href="https://hacktoberfest.digitalocean.com/"&gt;Hacktoberfest&lt;/a&gt; is an annual event in October that celebrates open source and encourages participation in the open source community. For me, it is the third time participating and I have some big plans for this year.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Theme
&lt;/h1&gt;

&lt;p&gt;I have spent a lot of time over the last year or so thinking about the intersection of &lt;em&gt;learning&lt;/em&gt;, &lt;em&gt;programming&lt;/em&gt;, and &lt;em&gt;gaming&lt;/em&gt;. More than a year ago I wrote the following piece on the topic, and my thinking has not changed much since:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.jdno.dev/why-i-want-to-build-a-video-game-for-programmers/"&gt;Why I Want to Build a Video Game for Programmers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the year that followed, I experimented with technologies and interfaces to test a few hypotheses. I hacked around with &lt;a href="https://bevyengine.org/"&gt;Bevy&lt;/a&gt;, a new game engine written entirely in Rust. I took my first steps with &lt;a href="https://godotengine.org/"&gt;Godot&lt;/a&gt;, and embedded a simulation written in Rust inside it. But the experiments have not yet led to an actual game, and I am not closer to original goal...&lt;/p&gt;

&lt;h1&gt;
  
  
  The Goal
&lt;/h1&gt;

&lt;p&gt;So the goal for October is to take what I learned in my experiments and start working on an actual &lt;em&gt;videogame for programmers&lt;/em&gt;. This is not a project that will be finished in a month, but in four weeks I want to have something that can at least be called playable.&lt;/p&gt;

&lt;p&gt;Concretely, I want to create the foundation for the videogame and implement a first game mechanic to prove the concept. It sounds simple, but requires me to shift from a prototyping to a product mindset and actually deliver something.&lt;/p&gt;

&lt;p&gt;The foundation that I refer to is everything that is required to work on the game. Code bases for the game's logic and the API layer, repositories on GitHub, continuous integration, and automation for common tasks to save myself time. I have written in the past about how I set up certain parts of my tooling (e.g. &lt;a href="https://www.jdno.dev/fully-automated-dependency-upgrades-with-dependabot-and-github-actions/"&gt;Fully Automated Dependency Upgrades with Dependabot and GitHub Actions&lt;/a&gt;), and I want to write one or two more articles in October about this topic.&lt;/p&gt;

&lt;p&gt;The game itself is something that will not fit into a single month. Truth be told, the vision that I hold in my head will require years of dedicated effort to implement a universe full of possibilities. But leaning into agile development practices, every cycle of work should produce a runnable product. And so should October...&lt;/p&gt;

&lt;h1&gt;
  
  
  The Plan
&lt;/h1&gt;

&lt;p&gt;A month sounds like a lot of time, but between my work and social life there is only so much time left to work on open source. So a plan is needed to use the time that I have in the most effective way possible. Roughly said, this is how I want the next four weeks to look.&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 1 – Foundation
&lt;/h2&gt;

&lt;p&gt;Building the foundation is the first step. I can cut some corners here and leverage work that I have previously done in my experiments. But I do need to think about a few questions without apparent right-or-wrong-answers. What architecture should the game have? What game engine best supports this architecture?&lt;/p&gt;

&lt;p&gt;Answering these questions is a daunting task, because they have the potential to set and restrict the long-term strategy for the game's development. But given my previous attempts, chances are high that this project will not live long enough for these decisions to be a problem. So let's just make them and move on...&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 2 – Game Mechanic
&lt;/h2&gt;

&lt;p&gt;The second week is dedicated to the development of the first game mechanic. I already have an idea in mind, and pages upon pages of notes and drawings in my notebook. So the challenge will be translating the idea into code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 3 – Developer Experience
&lt;/h2&gt;

&lt;p&gt;An hypothesis concerning the success of the game is that developer experience matters: If programmers can get started easily and find the resources they need to be successful in the game, they will like the game and play it. To test this, the third week is all about creating a good developer experience. A starter template for Node.js, good documentation, and a place to connect with the community.&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 4 – Validation
&lt;/h2&gt;

&lt;p&gt;The last week is less about coding, and more about exploring the mid-term future of the project. With a very rough but playable proof-of-concept in hand, what does the community think about the project? Is there interest to see this project continue? And if so, can I validate that it would be commercially viable for me to dedicate more time to it?&lt;/p&gt;

&lt;h1&gt;
  
  
  The Deliverables
&lt;/h1&gt;

&lt;p&gt;At the end of October, I want to have achieved the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Take the &lt;em&gt;videogame for programmers&lt;/em&gt; from idea to prototype. Release a small, playable version that demonstrates what can be possible...&lt;/li&gt;
&lt;li&gt;Validate the idea and answer the question whether it makes sense to invest more time into this project.&lt;/li&gt;
&lt;li&gt;Write more. So many ideas are only partially developed in my head and notebook, and I want to take time to put them into a coherent form and explore them on this blog.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope that putting these on paper creates the accountability I need to really follow through with them. The first day of October is already gone, 29 more days to go. Let's get started...&lt;/p&gt;

</description>
      <category>github</category>
      <category>opensource</category>
      <category>gamedev</category>
      <category>hacktoberfest</category>
    </item>
  </channel>
</rss>
