<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[The Tech Enabler]]></title><description><![CDATA[My personal Substack for my role as a tech enabler inside a large media company. I write about work, culture, and programming in general. My current series is all about tech trends and what I think teams should adopt or drop.]]></description><link>https://thetechenabler.substack.com</link><image><url>https://substackcdn.com/image/fetch/$s_!BQzA!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8ca672b-8408-4f12-aafd-37e9a28d3506_1047x1047.jpeg</url><title>The Tech Enabler</title><link>https://thetechenabler.substack.com</link></image><generator>Substack</generator><lastBuildDate>Wed, 13 May 2026 03:04:38 GMT</lastBuildDate><atom:link href="https://thetechenabler.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Noah Hall]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[thetechenabler@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[thetechenabler@substack.com]]></itunes:email><itunes:name><![CDATA[Noah Hall]]></itunes:name></itunes:owner><itunes:author><![CDATA[Noah Hall]]></itunes:author><googleplay:owner><![CDATA[thetechenabler@substack.com]]></googleplay:owner><googleplay:email><![CDATA[thetechenabler@substack.com]]></googleplay:email><googleplay:author><![CDATA[Noah Hall]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[On vibe coding: software engineers must be vocal about engineering]]></title><description><![CDATA[Do you remember the joy and excitement when you first started coding?]]></description><link>https://thetechenabler.substack.com/p/on-vibe-coding-software-engineers</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/on-vibe-coding-software-engineers</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Fri, 27 Mar 2026 20:09:38 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!BQzA!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8ca672b-8408-4f12-aafd-37e9a28d3506_1047x1047.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Do you remember the joy and excitement when you first started coding? If you were anything like me, it quickly became your main hobby. Something you&#8217;d do any chance you got. Even years later, it&#8217;s still my main hobby. It should be no surprise to any of us that vibe coders are delighted with what they can create, without the years of experience or knowledge.</p><p><em><strong>Except those years of experience and knowledge are important.</strong></em>  </p><p>Software engineers have done themselves a disservice by years of talking about &#8220;beautiful code&#8221;, &#8220;code ninjas&#8221;, and &#8220;tech wizards&#8221;. It has given outsiders the perspective that code is an art, something that has no significant meaning beyond cultural significance. Expect, it&#8217;s not.</p><p>Code turns logic into a tangible artifact, a repeatable pattern. Mathematics does the same. But the level of abstraction is high enough in code that we can nitpick over naming or styling. Regardless, code is a manifestation of logic.</p><p>As non-developers get their hands on LLMs, they&#8217;re ignoring the logical engineering approaches which software engineers follow. Their AI claims it is right, after all. </p><p>Should we blame the vibe coders for ignoring these practices? If they&#8217;re using production data, or deploying to production, a little bit. But the root problem doesn't go away by pointing fingers at early adopters. The root problem is that software engineering is not understood. </p><p>Drawing rivalries of &#8220;us vs them&#8221; isn&#8217;t useful. The vibe coders will continue regardless of how loud anyone protests, even if the protesting comes from experts or reporting lines.</p><p>While I&#8217;ve personally found generative AI largely low quality, I still think it can be a useful tool. In software engineering, we&#8217;ve spent years debating different tools. We know the saying &#8220;when all you have is a hammer, everything looks like a nail&#8221;. Vibe coders don&#8217;t know about the screwdriver, the drill, the spanner. They also don&#8217;t understand the limitations of the hammer. </p><p>Not every vibe-coded app requires expertise. If it&#8217;s a prototype thrown away after a week, then there&#8217;s no harm in terms of software engineering. But when you give people the ability to create things or solve problems in exciting ways, they become attached to their creations. Vibe coders will not throw away their smashed up wall, no matter how many holes it has in it. They aren&#8217;t aware of the holes. Again, their AI tells them it can fix anything and everything.</p><p>So, what can software engineers do? </p><p><strong>I have no idea</strong>. And it fills me with existential dread to see all the things I value being torn down: </p><ul><li><p>open source code has been shamelessly cloned by those who were trusted to look after it, and is now polluted beyond repair</p></li><li><p>the natural filter of ideation and development via a bottleneck is replaced with &#8220;let&#8217;s do all the features&#8221;</p></li><li><p>small features have large, messy code</p></li><li><p>security, intentional slowness has been replaced by &#8220;get X out the door ASAP&#8221;</p></li><li><p>resilience and reliability doesn&#8217;t exist when someone ships code they don&#8217;t understand</p></li><li><p>experts are being ignored, and companies are pushing ahead on hype alone</p></li></ul><p><strong>The clear path ahead, to me, is filled with chaos, security and privacy breaches, and downtime. </strong>We are already seeing the consequences of AI code reaching production: downtime across Big Tech. </p><p>We can&#8217;t educate everyone with access to an LLM about software engineer. If you give them things to read, they&#8217;ll ignore it. Software engineering has never needed degrees to be accomplished: but it has required experience and understanding, usually earned through interest. Generative AI tools lets vibe coders skip the experience and the understanding. </p><p>I don&#8217;t know the right answer. But I know that software engineering needs vocal voices to speak about the expertise, because being software engineers, we are often too eager to jump onto whatever the most fashionable tool is without much consideration for <em>is this right?</em></p><p>I have some hope. After all, this isn&#8217;t the only inflated hype bubble that we&#8217;ve run into. I think the clearest path I see:</p><ul><li><p>Move away from Big Tech models ASAP to cut through the massive moats being built through huge amounts of capital</p></li><li><p>Unions and academia should work to define what it means to do <em>software engineering</em> as it is in some countries. It should be a licensed activity. Anything else is &#8220;sparkling vibe-based text generation which happens to look like code&#8221;. Clearly define the difference between <em>engineering</em> and <em>vibing</em>. There are plenty of good use cases for AI. Deploying to production is not one of them. The practices of software engineering need to be clearer to non-developers.</p></li><li><p>Educate the vibe coders as quickly as possible, so they actually understand the impact of their code on companies, systems, and worst of all - their software engineering expert colleagues.</p></li><li><p>Run vibe coding tools remotely, in containerized environments via a web browser. Definitely not running code on local devices.</p></li></ul><p>I don&#8217;t know. </p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/on-vibe-coding-software-engineers?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/on-vibe-coding-software-engineers?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[The Mythical AI-agent Month]]></title><description><![CDATA[&#8220;The Mythical Man Month&#8221;  states adding more humans to a project did not reduce the time to complete, but rather increased it. How does this apply to AI agents?]]></description><link>https://thetechenabler.substack.com/p/the-mythical-ai-agent-month</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/the-mythical-ai-agent-month</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Sat, 31 Jan 2026 14:40:53 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/49d82113-fbc4-41dc-93d5-b0e0c4e9d764_1373x468.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>&#8220;The Mythical Man Month&#8221; used to be required reading at many universities for computer scientists.  The book states adding more humans to a project did not reduce the time to complete, but rather increased it. Yet with the advent of AI coding agents, it seems to me like some people have thrown it out the window.</p><p>Brooke&#8217;s law: </p><blockquote><p><em>Adding manpower to a late software project makes it later</em>.</p></blockquote><p>As the manpower for a project increases, the amount of coordination increases. A team of 8 people will often find themselves needing to fix merge conflicts, talk with each other about features or bugs, and decide who works on what and when. A single person project might produce less overall code, but the entire context lives inside that person&#8217;s mind. Adding one extra person completely changes the dynamic. &#8220;2-pizza teams&#8221; are approximately 8 people, usually with some split expertise. The overhead is substantial, but many find it a good balance between overhead and production. </p><p>Open source projects scale to many more contributors, but the number of core contributors remains relatively low. There just aren&#8217;t that many people who know the codebase in-and-out to the extent that mass collaboration is possible, therefore pushing collaboration to the conceptual level, or one-off-issues.</p><p>The bus number for a single person project is 1. Far too low for anything intended for large scale production. If that person is gone, the project is dead. Even for huge open source projects like the Linux kernel, <a href="https://www.scannedinavian.com/the-github-plugin-my-coworkers-asked-me-not-to-write.html">the bus factor is very low.</a> It is difficult for contributors to have the complete overview. The evidence from corporate and open source coding reveals a learning: a well maintained project cannot have hundreds of key people, but it also can&#8217;t have one key person only.</p><p>Over time, teams or open source communities identify better ways to work together. If they don&#8217;t, then they stop existing. Routines, habits, and interactions become codified as a way of working.  </p><h3>So what does all this mean in the context of AI agents?</h3><p>First, let me try to define my personal definition for the sensible production use of generative AI for code. What does generative AI do? It takes some input, usually text, and produces an output, usually text. This is not anything new. Parsers and compilers have existed as long as high-level programming languages have. Is the logic linear? Is the logic repeatable? Nope. It is more similar to search than a parser - ephemeral results from a known input. It is not deterministic. </p><p>IDEs have had auto-complete for decades. Generative AI is a fancy auto-complete that <em>seems</em> intelligent. But it&#8217;s not intelligent. &#8220;Reasoning models&#8221; don&#8217;t reason. &#8220;Thinking models&#8221; don&#8217;t think. They take text, run it through a model trained on code, and produce similar output to what they have been trained on.  </p><p>Therefore, I would define sensible production use of generative AI for code as <em>&#8220;the use of AI to produce code in a controlled manner such as an auto-complete suggestion, or search, with a human software engineer in the loop&#8221;.</em></p><p>If AI for coding is used sensibly, a software engineering human will review and own the code before it is pushed to production. The AI produced code becomes just another way for a software engineer to transfer their ideas into code. AI auto-completion falls into this category. The software engineer takes responsibility for any bugs or security issues introduced through their code. There is no additional manpower added to the project, but the manpower may get more efficient. Brooke&#8217;s law does not apply in this case. </p><p>But the flow with AI agents is substantially different. Rather than an auto-complete, AI agents go away, figure out some code they deliver, and the human&#8217;s input is minimal except for describing the feature and finally reviewing the code. The output of the AI agents adds &#8220;AI power&#8221; to the project, which triggers Brooke&#8217;s law. A human may merge the code, and therefore take responsibility, but here&#8217;s the thing: <strong>software engineers are bad at reviewing code they didn&#8217;t write.</strong> A sensible project will require strict reviews, QA, testing of any AI produced code. Humans are just not good enough at reviewing code. Maybe one day we will be, but <strong>the tools we have available to us today are built with </strong><em><strong>producing code</strong></em><strong> in mind, not </strong><em><strong>reviewing code</strong></em>.</p><p>I&#8217;ve used and tested AI agents. I&#8217;ve read the docs, I&#8217;ve listened to people who claim they&#8217;re able to produce high value code through them. I suspect I have a higher threshold for code merges than most people, particularly on solo projects. AI agents are being hyped as a way to code without needing to write it yourself. Spin up an AI agent, send it off, done. I have not found that to be true. Every single change and commit needs manual verification. Every single change and commit has the potential to introduce code so harmful to the codebase, either due to poor readability or poor implementation, that I have reflected multiple times <em><strong>why does anyone do this? Why am I doing this? I could&#8217;ve saved myself time by writing it myself</strong>. </em></p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!SDAP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F396fb1dc-4ba4-430f-abf4-d65c3b3275bc_1373x468.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!SDAP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F396fb1dc-4ba4-430f-abf4-d65c3b3275bc_1373x468.png 424w, https://substackcdn.com/image/fetch/$s_!SDAP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F396fb1dc-4ba4-430f-abf4-d65c3b3275bc_1373x468.png 848w, https://substackcdn.com/image/fetch/$s_!SDAP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F396fb1dc-4ba4-430f-abf4-d65c3b3275bc_1373x468.png 1272w, https://substackcdn.com/image/fetch/$s_!SDAP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F396fb1dc-4ba4-430f-abf4-d65c3b3275bc_1373x468.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!SDAP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F396fb1dc-4ba4-430f-abf4-d65c3b3275bc_1373x468.png" width="487" height="165.9985433357611" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/396fb1dc-4ba4-430f-abf4-d65c3b3275bc_1373x468.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:468,&quot;width&quot;:1373,&quot;resizeWidth&quot;:487,&quot;bytes&quot;:52778,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/185722725?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F396fb1dc-4ba4-430f-abf4-d65c3b3275bc_1373x468.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!SDAP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F396fb1dc-4ba4-430f-abf4-d65c3b3275bc_1373x468.png 424w, https://substackcdn.com/image/fetch/$s_!SDAP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F396fb1dc-4ba4-430f-abf4-d65c3b3275bc_1373x468.png 848w, https://substackcdn.com/image/fetch/$s_!SDAP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F396fb1dc-4ba4-430f-abf4-d65c3b3275bc_1373x468.png 1272w, https://substackcdn.com/image/fetch/$s_!SDAP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F396fb1dc-4ba4-430f-abf4-d65c3b3275bc_1373x468.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>I acknowledge that my own threshold to merge might not be the same as others. However, there&#8217;s some things I value both in my own work, and the work of others. </p><ul><li><p>Minimalism. Code that only exists because it has to. Low-noise, high-signal. </p></li><li><p>Architecture driven by good types and data structures. </p></li><li><p>Changes that are easy to understand or rollback. </p></li><li><p>Security as a guiding principle, not an after-thought.</p></li><li><p>Human verified. Natural ways to interact with the product (e.g CLI, TUI, GUI, APIs).</p></li><li><p>Code I can read, understand, and change.</p></li></ul><p>The AI agents I&#8217;ve tried have all failed in these regards. Even with instructions, they have produced incredibly noisy code. </p><p>Inventing new functions when a function already exists that will serve the purpose. Comments that mean nothing. Inlining code where it adds nothing. Types which have been ignored. Repeated bad habits that I would expect a junior to learn from. Changes which are just too big to understand. Pull requests that end up with hundreds of comments before it&#8217;s worth merging. Security issues while asserting &#8220;this code has been generated with security in mind&#8221;. Agents that tell you confidently &#8220;I&#8217;ve fixed the problem&#8221;, while the problem is still clearly there. </p><p>I would be ashamed to push that code to production. But <strong>most concerning</strong><em><strong>, it would introduce AI-produced code that would slow down the humans working on the project</strong>. </em>Either as the reviewer, or as the poor soul who would then have to work with such a codebase. </p><p>Suddenly the overhead increases from beyond merge conflicts, or schedule management. It becomes a factor of <em>something unintelligent made this code. </em>Something, not someone. Something that doesn&#8217;t actually understand what it did, or why. Something ephemeral, where learnings are brief unless it is retrained or has added context. Something that can&#8217;t take responsibility. Something that needs human coordination. Therefore, the overhead with AI agents is larger than that of a human. <strong>And no, getting AI agents to review code made by other AI agents is not a fix for the problem. It just means you&#8217;re shipping code you don&#8217;t understand, but you are responsible for.</strong></p><p>Just like the mythical man month, the mythical &#8220;AI agent&#8221; month remains just that: mythical. Not everyone will realize the myth right now. But in 2 years time, when they can&#8217;t find anyone to work on their nightmare codebases, they will.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/the-mythical-ai-agent-month?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/the-mythical-ai-agent-month?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[My personal love of open source]]></title><description><![CDATA[I&#8217;ve been reflecting on why I personally love open source software. Just me, my brain, and my heart.]]></description><link>https://thetechenabler.substack.com/p/my-personal-love-of-open-source</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/my-personal-love-of-open-source</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Thu, 11 Dec 2025 16:05:44 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!BQzA!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8ca672b-8408-4f12-aafd-37e9a28d3506_1047x1047.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I&#8217;ve been reflecting on why I personally love consuming open source software.I&#8217;m going to put aside why I believe open source is important for companies and digital sovereignty. No business speak, no bullshit. Just me and my heart.</p><p>When I use software, I find bugs. When I find bugs, I want to report them or fix them. </p><p>If I find a bug on a small company&#8217;s website, I email them with the fix<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>. Often it&#8217;s something small, like bad contrast. Sometimes it&#8217;s even smaller, like a typo. If it&#8217;s bigger, I&#8217;ll usually include some description of how I think they can solve the problem. Very rarely, I&#8217;ll offer to implement a fix for the company. I&#8217;ve almost always done this entirely free in the past. If the site is one I use often, I want it to work well. And if it&#8217;s not one I use often, then it&#8217;s neat to be able to say &#8220;I did that&#8221; occasionally.</p><p>As a company grows, I am less likely to send them feedback. The biggest factor is that it&#8217;s <em>hard</em> to give feedback to a larger company. A smaller company often has one email address, and you&#8217;ll get an actual human replying to you. Figuring out who to email inside a bigger company is so difficult that people used to take to Twitter in order to get any traction. If I&#8217;m spending time to report an issue, I want to know my time has been well spent and worthwhile.</p><p>Most bugs are minor annoyances I can live with, but bigger bugs are something I want to follow closely. </p><p>When the code for a tool I use is open source, I will usually either make an issue or submit a pull request. From there, I can see the entire chain between issue creation, code merging, and release. I can even run a branch locally. I cannot do the same in closed-source code. I must wait and hope that the bug is fixed. </p><p>There&#8217;s been many times where I&#8217;ve encountered a bug I know I could fix if I had access to the codebase. Problems I&#8217;ve reverse engineered to find a solution, often out of my own personal curiosity. </p><p>I follow the mantra: &#8220;leave things better than when you found it&#8221;. Open source allows me to leave things better - to clean up bugs, to write documentation, or partake in feature discussion. I find the collective energy in open source communities inspiring. </p><p>To all those forgotten unpaid maintainers, to all those people who help lift up a project, you are all collectively leaving technology a better, more useful, place than how you found it.</p><p>Open source is where I learnt to be a developer. It&#8217;s how I learned to interact with developers and assume good intentions. It&#8217;s where I learnt how to develop languages, it&#8217;s where I learnt that one piece of code can have a big positive impact. It&#8217;s where I learnt how to manage backlogs. It&#8217;s where I learnt to approach new communities with an open mind. But most of all, it&#8217;s where I learnt how to be passionate about code.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/my-personal-love-of-open-source?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/my-personal-love-of-open-source?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>As small companies usually don&#8217;t have in-house technical resources, I avoid using too many technical terms. It&#8217;s not great if your attempts to help are perceived as red-teaming by someone who doesn&#8217;t understand what HTML is.</p><p></p></div></div>]]></content:encoded></item><item><title><![CDATA[Testing a human bottleneck]]></title><description><![CDATA[What happens when a key operational person goes on vacation?]]></description><link>https://thetechenabler.substack.com/p/testing-a-human-bottleneck</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/testing-a-human-bottleneck</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Sun, 30 Nov 2025 16:22:57 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!BQzA!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8ca672b-8408-4f12-aafd-37e9a28d3506_1047x1047.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Too many dependencies on few resources creates bottlenecks. Usually bottlenecks are a bad thing, as they reduce the overall throughput of a system. Bottlenecks can be good: they limit the load on downstream or upstream resources. But they make a system slower, either intentionally or unintentionally.</p><p>As an enabler, I become involved in many different discussions between different people in the organisation. When people reach out to me, it can be considered a reflection of how much value they get from my assistance. At the same time, it can reflect a lack of documentation, a lack of established workflows, or a lack of a shared overview.</p><p>In the last couple of years, I&#8217;ve taken a full vacation out of season. In the Nordics, summers and school holidays tend to leave offices empty. I work during those periods, and travel when most people are at work.</p><p>The great thing about going AWOL for so long is that it forces the company to function without me. Many things will either become irrelevant, or solve itself through people connecting directly. Anything else can wait. It's unhealthy when a company that can&#8217;t handle a couple of key people being gone for an extended period of time.</p><p>I&#8217;m a strong believer in constantly trying to make manual work I do redundant. The more of my time I free up, the more involved I can be where it matters. </p><p>To prepare people for my absence, I let the people I work with the most know ahead of time. This year I created an offboarding document, exactly as I would if I was leaving the company. I went through the topics that people reached out to me about in the last 2 months, and listed who they should talk to in my absence - defaulting to a channel rather than an individual. I put a status for each project I was involved with, and provided links to reports or docs people often ask me about. I shared the document with everyone, giving them a couple of days heads up to ask any questions before I&#8217;m gone.</p><p>Some of the value of my role comes from all the extra bureaucratic issues that I can reduce. Two groups of people should be most effective when talking directly, but a wide range of reasons can introduce significant overhead. In these scenarios, I can help clear cultural or organisational barriers, or provide direction and alignment with the company strategies and goals. I see this as reactive: a team has a need, and reactively I work to help them solve that need. But I want to be redundant in these scenarios too, which leads into proactive work to establish and grow the culture and processes.  </p><p>It is hard to go away for a month, but it&#8217;s very much worth it for me personally. I&#8217;ve been burnt out a couple of times in the past, so vacation is highly crucial for me. My family and friends mostly live far away, making short week vacations difficult. 7 days when 3 of those days are spent travelling isn&#8217;t really a vacation in which I can relax. But a month where I know I have no work obligations is a true vacation for my brain. A clean handoff means that I won&#8217;t be worrying about paintings half painted, questions waiting for my answer.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/testing-a-human-bottleneck?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/testing-a-human-bottleneck?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[Bring your colleagues along for the journey]]></title><description><![CDATA[I believe that when a difficult decision must be made, you should always bring along with you the key stakeholders.]]></description><link>https://thetechenabler.substack.com/p/bring-your-colleagues-along-for-the</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/bring-your-colleagues-along-for-the</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Fri, 14 Nov 2025 22:48:35 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!BQzA!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8ca672b-8408-4f12-aafd-37e9a28d3506_1047x1047.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I believe that when a difficult decision must be made, you should always bring along with you the key stakeholders. Even if the final decision isn&#8217;t what they&#8217;d ideally like, they will be more understanding if they were part of the journey.</p><p>In my role at work, and in Tekna, I constantly try to push the needle. If something is not working, I want to fix it. If something is not good, it needs to be changed. Not everything can be fixed, and fixing things takes time.</p><p>Sometimes that can come across as a strong opinion. Sometimes, it is. I try to back my opinions with facts, but I&#8217;m human - sometimes I like things just because I like them. I try to be as introspective, and question why I like things. Sometimes I figure it out, sometimes I settle for being human.</p><p>Pushing the needle needs strong voices. Europe is undergoing a drastic change in relation to the USA, and we need voices in Europe who can guide the way. I don&#8217;t think that is necessarily me, but until there&#8217;s a clear path ahead, I will be sharing my voice. I&#8217;ve spent a lot of reflecting on my opinions, and a lot of time gathering data.</p><p>However, collectives of people begin to suffer when fear, uncertainty, and doubt set in. If colleagues *feel like* they can no longer depend on other teams to act in the best interest of each other, trust is broken. When trust is broken, it is extremely damaging to an organisation. In open source collectives, damaged trust is enough to kill projects or collaborations. In work collectives, it eats up so much time and effort to undo the damage. </p><p>Often employees would rather leave than to remain working with those they no longer can depend on - worse still, sometimes they&#8217;ll stay in the company but sever all ties and actively work to avoid each other.</p><p>I take the time to get to know my colleagues. I don&#8217;t want to doubt them, I don&#8217;t want them to doubt me. I want them to feel certain that they can depend on me to do my job, and I want to be certain I can depend on them to do their job effectively. </p><p>Every time a decision is made behind closed doors without good technical or culture insight, I&#8217;ve seen it cause fear, uncertainty, and doubt (FUD). Every time I've seen FUD set in, it&#8217;s created a waste of time, energy, and resources. It takes so much effort to establish trust, and so little to destroy it. </p><p>My advice is always the same: talk to people, bring them along for the journey, and actually understand the problem you&#8217;re solving. Most people have good intentions by default. But a failure to communicate or introspect turns good intentions to bad implementations. Don&#8217;t give fear a chance to grow.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/bring-your-colleagues-along-for-the?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/bring-your-colleagues-along-for-the?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p>]]></content:encoded></item><item><title><![CDATA[Software engineering primer for non software engineers]]></title><description><![CDATA[With AI providing a route for people without software engineering backgrounds to produce code, I figured giving some context on the important parts of software engineering would be useful.]]></description><link>https://thetechenabler.substack.com/p/software-engineering-primer-for-non</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/software-engineering-primer-for-non</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Tue, 21 Oct 2025 16:48:33 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!BQzA!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8ca672b-8408-4f12-aafd-37e9a28d3506_1047x1047.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>With AI providing a route for people without software engineering backgrounds to produce code, I figured giving some context on the important parts of software engineering would be useful. Each topic in this article is one I&#8217;d expect a junior developer to be aware of, and I&#8217;d expect a senior developer to be deeply familiar with.</p><p><em>A note: I&#8217;ve simplified some concepts and some names.</em></p><h1>Code</h1><p>Code is the fundamental part of all software engineering. It represents an idea, a flow, a behaviour.</p><h3><strong>Programming languages</strong></h3><p>Standardized ways of writing code so that the machine can run them are called <em>programming languages</em>. Programming languages define a <em>syntax</em> and <em>grammar</em>, which are then implemented by parsers, compilers, and interpreters. Programming languages allow a human to turn ideas, concepts, or thoughts into structured code that a machine can understand. Each language has a different mental model, and a different feel. As this is a direct form of creativity, many developers have strong feelings about the programming languages they use.</p><p>There are different <em>families</em> of related or derivative programming languages. Languages within the same family will share many of the same concepts, but may differ in implementation or syntax. Knowledge in one programming language in a family will usually greatly help a developer understand other languages in the same family. Programming language design is highly iterative, developing concepts from other languages.</p><h3><strong>Functions</strong></h3><p>The repeated use of certain pieces of code can be turned into logically distinct reusable code called <em>functions</em>. Depending on the language, they may also be referred to as <em>methods</em> or <em>procedures</em>. There are small differences in the definition of each, but regardless, they serve the same purpose - to describe a specific behaviour that operates using specific data. That behaviour can be reused in multiple places by running the function.</p><p>Functions may take <em>arguments</em> or <em>parameters</em>. Arguments allow data to be used from elsewhere in the program. A good function has a clear purpose, with a limited yet useful set of arguments. A function that serves too many purposes makes code harder to understand.</p><h3><strong>Types</strong></h3><p>The structure of data informs the usage of the data. <em>Types</em> provide both humans and computers with information on the structure. The structure guides the implementation of functions. Types also enforce contracts between code, so that invalid or incorrect usage is caught during development rather than when the program is running. At a basic level, types ensure the data is of the correct family (numbers, strings, booleans). At an advanced level, known as type driven development, types provide restrictions on possible values of data so that there&#8217;s only a specific subset of values.</p><p>Every mainstream language has a form of types. The way that types work, known as the type system, often share common behaviours and features across a family of languages. However, the idiomatic usage varies greatly between languages. TypeScript, Python, Java, C, Rust, Haskell all have very different approaches to types, even with considerable overlap. The choice of language therefore impacts the structure of data, and therefore impacts the architecture of your program.</p><h3><strong>Schema</strong></h3><p>Data may have a known structure called a <em>schema</em>. A schema, much like types, ensures the properties of data for both human purposes and machine purposes. A human uses a schema to understand data, whereas a machine uses a schema to verify the data it receives is of the correct structure.</p><h3><strong>Lists and arrays</strong></h3><p>Lists and arrays provide a collection of related data in such a way that each item in the collection can be used or manipulated via <em>iteration</em>. Arrays are typically the most efficient collection storage with the lowest overhead, leading to their prevalence as a concept in most programming languages. In some languages, lists and arrays must contain elements of the same type. In others, the elements may have different types.</p><h3><strong>Hashmaps and dictionaries</strong></h3><p>Maps provide a structure where a collection of elements can be accessed via a label very quickly. They are often used for data where there are named fields which the developer may not know when they are writing the code. Most languages have some type of map collection.</p><h3><strong>Objects</strong></h3><p>Data may be combined with functions that work specifically with that data. In <em>object-oriented programming (OOP)</em>, objects are the main concept used to define behaviours and limit access to data. Objects have different implementations in different languages, while the purpose usually remains the same.</p><p>The structure and relationships of objects may be defined through a constructor called <em>classes</em>. Classes may have relations to other classes or types.</p><p>Not all languages have classes, though most have a construct that serves a similar purpose.</p><h3><strong>Scope, local vs global</strong></h3><p>Reducing the cognitive load of code uses <em>scope </em>to limit where different code is used. Most languages have some distinction between the scope of data, functions, and types. Scope allows for different data to be referred to by the same name, or limit what developers have access to elsewhere in the program. Scope restrictions guide architecture, and reflect architecture. <em>Local</em> scope refers to items within a small block of code, such as a function. <em>Global</em> scope refers to items accessible throughout the entire program or file. The majority of items should be within the <em>local</em> scope of a function or class, with very few items in the <em>global</em> scope.</p><p>When considering performance optimization, items within the <em>global</em> scope are difficult to optimize as they must be accessible in more situations when compared to those in the <em>local</em> scope. This plays a factor when reducing the memory usage of an application, as <em>garbage collection</em> will cleanup data that no longer needs to be accessible.</p><h3><strong>Object-oriented programming</strong></h3><p>Programming languages that focus on objects and classes are known as <em>object-oriented programming languages</em>.</p><h3><strong>Functional programming</strong></h3><p>Programming languages that focus on the use of functions belong to a paradigm of languages known as <em>functional programming</em>.</p><h3><strong>Immutable</strong></h3><p>A value which cannot be changed is known as <em>immutable</em>. Immutable values allow a programming language or framework to apply optimizations, while also reducing unexpected behaviour due to unexpected changes of data. Some programming languages, like functional programming languages, may have every value stored as immutable data. Others may not have any immutable values.</p><h1>Engineering</h1><p>Code is only part of engineering, with software engineers needing to know many adjacent topics.</p><h3><strong>Security</strong></h3><p>As code allows for applications to scale to millions of users, it also provides a way to scale security exploits to millions of users.</p><p>Humans make errors. AI makes more errors. A good software engineer will acknowledge that they are not perfect, and take steps to reduce potential security attack surfaces, and use tools to automate security analysis.</p><h3><strong>Logging</strong></h3><p>To aid with debugging and optimization, applications should provide <em>logs</em> to developers. These logs typically include metadata about a user&#8217;s device, any actions taken, and communication between services. Logged errors help a developer identify the root cause of a problem.</p><p>Logging too much data can create privacy and security breaches. A typical example is logging passwords or accessing tokens in plaintext, therefore leaking them.</p><h3><strong>Supply chains</strong></h3><p>The security of the program applies to all the code that the program uses, not only the bespoke code written for the program. For frontend code, that includes libraries used in user-facing code and the build chain used (e.g esbuild). For backend code, that includes libraries, tools, and the operating system itself. Software engineers have a legal obligation to ensure that libraries are up to date to prevent security risks. As a result, using fewer, well-trusted libraries reduces the attack surface.</p><h3><strong>Performance</strong></h3><p>Different languages, frameworks, and libraries have different performance levels. Choosing the right tool for a problem is something a software engineering team will balance against what is enjoyable, and what they know. Performance is a trade-off to consider along with other reasons to use a specific tool - rarely is the fastest tool is the most used tool. When comparing tools, it&#8217;s important to compare apples to apples. Two different frameworks in two different languages are mostly irrelevant unless a team is willing to rewrite the codebase to a new language.</p><p>Even within the same language, a performance-optimal implementation of logic might be rejected in favour of a more readable implementation. A good software engineer will know when and where to apply performance optimisation. Before time is spent on optimising performance, gathering metrics on the runtime ensures that time is spent on the right parts.</p><h3><strong>Compilers and interpreters</strong></h3><p>Code written in high-level languages must be turned into a form that can be understood by a computer. There are two main forms: <em>compilers</em> and <em>interpreters</em>. A compiler will turn high-level code into machine-compatible code before the program code is run, whereas an interpreter will turn high-level code into machine-compatible code as the program is running.</p><p>It is easier for a compiler to apply type checks, syntax checks, and performance optimisations than for an interpreter as the entire program is understood (parsed) before the code has been run. However, interpreted code is typically faster to begin running as there is no step before running required to parse and generate code.</p><p>The differences between the two aren&#8217;t as significant in modern development as they used to be. However, the difference in mindset remains an influence in development. Interpreted languages like JavaScript or Python come with an expectation of a fast turnaround for development, whereas compiled languages like C or Rust come with an expectation of a fast runtime after the program has been compiled. As a result, interpreted languages tend to involve a faster loop testing out ideas, while compiled languages have a lot of surrounding tooling.</p><h3><strong>Abstraction</strong></h3><p>Re-usable code and data is often <em>abstract</em>. Instead of applying for a very specific set of values, an abstraction may vary in the values used. A function with arguments and a return value is a form of abstraction, as are types and classes.</p><p>A software engineer will need to balance code between abstraction and specificity. Abstract code comes with benefits such as simplify code reuse and relationships, but may introduce cognitive load and performance issues.</p><h3><strong>Code duplication</strong></h3><p>When code is repeated, it adds more places where bugs or changes must be implemented. To avoid tech debt, a developer will seek to replace duplicated code with one, more abstract piece of code. This is known as DRY - don&#8217;t repeat yourself.</p><h3><strong>Architecture</strong></h3><p>The design of technical systems is known as the architecture. Interactions between different services or code are guided to the <em>architecture </em>of the system. At the highest level, the architecture might be represented by diagrams or specifications. The architecture of a corporate codebase is often a reflection of the organisation (Conway&#8217;s law). However the architecture of open source codebases often reflect the personal preferences of the contributors, as libraries reflect the needs of many different corporate or non-corporate entities.</p><h1>Workflow</h1><p>A software engineer&#8217;s workflow is vital to their success. A messy workflow often results in messy engineering.</p><h3><strong>Debugging</strong></h3><p>The process of identifying and fixing bugs is known as <em>debugging</em>. Debugging is a skill built up through familiarity with the tools used (languages, frameworks, libraries) and the project itself. There are many tools for debugging, often language or framework specific. The concepts of debugging are roughly the same across all tools however.</p><p>A software engineer should be able to both recall bugs they&#8217;ve encountered before (and sometimes avoid repeating them), and find new bugs they haven&#8217;t encountered before. While senior developers might have a larger set of bugs they&#8217;ve encountered, junior developers can still be highly skilled debuggers through adaptive learning.</p><h3><strong>Tests</strong></h3><p>Automated reproduction of behaviour and validation of the results are known as <em>tests</em>. Testing too little reduces the confidence a developer may have in changes they made. Testing too much slows down development. A collection of tests are known as a <em>test suite</em>. Good test suites are run frequently, covering enough of the behaviour of the program that possible unintended changes or implications of behaviours are caught. If a test suite is too large, it will take a long time to run. If it takes a long time to run, developers will run the tests less often - reducing the value of the test suite.</p><p>Different types of tests are used for different scenarios. Tests which only test a specific function in isolation are known as <em>unit tests</em>. Tests which test an entire program are known as <em>end-to-end</em> tests. Tests which test a specific interaction between two elements of a system are known as <em>integration tests</em>. Each form of test has a well-suited purpose.</p><p>Unit tests could be used to verify one part of an algorithmic calculation. End-to-end tests could be used to ensure that a mobile app behaves as intended. Integration tests could be used to verify parts of a complicated system. A large production codebase normally needs a mixture of different types of tests for different parts of the system.</p><h3><strong>Source control</strong></h3><p>Every change a developer makes must be stored in a way that allows easy understanding of changes. A <em>patch</em> describes the changes to some code at a specific point in time. A patch will be attached to a <em>commit</em> which contains metadata about the patch, such as a description by the developer. Multiple commits may be combined to form a <em>pull request</em> which describes some set of feature changes, including bug fixes. A pull request is typically reviewed before it is added to a codebase by a <em>merge</em>. A pull request review provides feedback for the developer, often with changes requested to address an issue with the proposed patches.</p><p>The history of a codebase is represented through the commits, aiding developers in understanding when and why things were changed. Understanding the context of changes allows developers to fix or prevent bugs with greater ease.</p><p><em>git</em> is the most widely used form of source control, though many other forms exist.</p><h3><strong>Open source</strong></h3><p>Unlike physical commodities, a critically significant portion of code is made freely available. This is known as open source - I.e, the source code is openly available. There are four fundamental freedoms granted by open source: the right to access code, and the right to use code, the right to modify code, and the right to redistribute modified code.</p><p>There are many forms of licenses that apply these freedoms to the code of a project to varying extent. The most common license families are BSD, GPL, Apache, and MIT. Different communities will default to a particular license. The license chosen has a significant impact on the potential users of a library, as some licenses impact the copyright of associated code.</p><p>Without open source, the rapid growth of the digital era would not be possible. Even more relevant to the reader, without open source, LLMs would not have been able to train on enough data to be useful coding assistants.</p><p>The majority of open source is hosted on Github, which provides a platform for managing source code versioning. Other platforms exist, however Github achieved market dominance several years ago. Open source projects have trouble with funding. For the value they provide to society, they are severely underfunded. Licenses of Github Copilot do not provide any compensation to the open source projects the LLM models are based on.</p><h3><strong>Tech debt</strong></h3><p>The choices made to implement a feature have an impact on the rest of the features you later implement. The accumulation of these choices is known as <em>tech debt</em>. Tech debt slows down feature development, and introduces bugs. Tech debt has many forms, including code for old features which are no longer used, data which is no longer accurate, or systems that have not been updated.</p><h3><strong>Pair programming</strong></h3><p>The process of two software engineers working together synchronously is called <em>pair programming</em>. Pair programming has many different forms. Pair programming aids knowledge transfer between two software engineers, often acting as a form of review in real time. Larger groups of software engineers are known as <em>mob programming</em>. Mob programming requires good coordination and facilitation to be productive.</p><h3><strong>Continuous integration</strong></h3><p>When a change is made, it must go through verification that the changes are valid. The verification is usually some combination of automated tests and manual tests. Different industries have different forms of verification. Once the changes have been verified, they are merged to the codebase.</p><h3><strong>Continuous deployment</strong></h3><p>When changes are merged to the production codebase, they need to be deployed to the user. Products that involve some input from the user to update (e.g operating systems) often deploy their changes to production on a regular basis. Web applications, where the user does not need to update anything themselves, are typically deployed as soon as the changes are merged through continuous deployment. Continuous deployment keeps application up to date without any additional overhead for the developer when compared to a release management.</p><h3><strong>Rollbacks and reverts</strong></h3><p>If a change is found to have a bug, there are three options: 1) fix the change and deploy the fix, 2) acknowledge the bug to be fixed later, or 3) rollback the current deploy to the previous deploy.</p><p>Small bugs with known fixes are often fixed and deploys. Bugs that don&#8217;t impact the overall user experience can wait. Bugs that will take longer to fix and have a critical impact should be rolled back. Rollbacks require that the previous code is able to run correctly, which may not always be possible. For example, if the broken latest commit modified data to a new schema, the data must be modified back to the previous schema before the previous code is able to run correctly.</p><div><hr></div><p>This post will be a living document, and I&#8217;ll revisit sections in the future.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/software-engineering-primer-for-non?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/software-engineering-primer-for-non?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p>]]></content:encoded></item><item><title><![CDATA[Norwegian Elections and news tech preperations]]></title><description><![CDATA[Last election, Norway&#8217;s biggest news site (VG) went down for around 3 hours. This time, we made sure it didn't.]]></description><link>https://thetechenabler.substack.com/p/norwegian-elections-and-news-tech</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/norwegian-elections-and-news-tech</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Tue, 09 Sep 2025 10:23:05 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!uXvu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfb16a18-811f-4f89-8152-5bfdfa293897_5712x4284.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Last election, Norway&#8217;s biggest news site (VG) went down for around 3 hours. This time, we made sure that didn&#8217;t happen.</p><p>That previous downtime was frustrating for the newsroom. Elections are one of the biggest nights in any newsroom. Being unable to reach users during an election, for Norway&#8217;s biggest news site, is painful.</p><p>Several factors had changed since last time. We learned from our mistakes. We benchmarked and tested. We pulled in resources from the entire organisation to ensure we didn&#8217;t have a failure point we couldn&#8217;t fix in moments. We handled the tech side so the journalists could focus on journalism. </p><p>Not only did our biggest news site stay up, but all our sites did. And our coverage of the results were ahead of every mainstream publication in Norway.</p><p>I took the role of incident commander - both in the lead up, and during election night. I prepared with a sleeping bag, a change of clothes, snacks and paracetamol. Since the previous election's downtime had caused uncertainty, it was important to communicate to the newsroom that <strong>we were here and ready to fix any problem that might happen</strong>. Not just on our messaging apps, but physically in person. <strong>The newsroom needed to be confident in us</strong>. By showing that we were ready to be there all night if needed, we were telling the newsroom: <em>we are here with you</em>.</p><p>Almost all the work was done long before the election. We had changed infrastructure, we had changed code and config. And we were wiser. There was one factor out of our control though: in previous years the media houses would receive the results prior to them being announced. This year, all the results would go public at the same time as the media houses received them. It introduced some anxiety in our team, but we were ready.</p><p><strong>09:00</strong> - Raise awareness of the incident channel for stakeholders. We want those invested to know where to find us. We wanted all the issues in one channel.</p><p><strong>09:40</strong> - State the rules, timing, and contact methods in the incident channel. Make it clear how things will be done.</p><p><strong>17:00</strong> - Go to the communication leads of the newsrooms and let them know we were there. Instill confidence not only in the technical solution, but also in communication and resilience. The newsroom needed to know they could reach out to us, any time, with any problem.</p><p><strong>20:00</strong> - We setup a physical meeting room where the newsroom can see us, but we&#8217;re apart enough to be able to focus. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uXvu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfb16a18-811f-4f89-8152-5bfdfa293897_5712x4284.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uXvu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfb16a18-811f-4f89-8152-5bfdfa293897_5712x4284.jpeg 424w, https://substackcdn.com/image/fetch/$s_!uXvu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfb16a18-811f-4f89-8152-5bfdfa293897_5712x4284.jpeg 848w, https://substackcdn.com/image/fetch/$s_!uXvu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfb16a18-811f-4f89-8152-5bfdfa293897_5712x4284.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!uXvu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfb16a18-811f-4f89-8152-5bfdfa293897_5712x4284.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uXvu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfb16a18-811f-4f89-8152-5bfdfa293897_5712x4284.jpeg" width="397" height="297.75" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dfb16a18-811f-4f89-8152-5bfdfa293897_5712x4284.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1092,&quot;width&quot;:1456,&quot;resizeWidth&quot;:397,&quot;bytes&quot;:1931676,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/173163105?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfb16a18-811f-4f89-8152-5bfdfa293897_5712x4284.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!uXvu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfb16a18-811f-4f89-8152-5bfdfa293897_5712x4284.jpeg 424w, https://substackcdn.com/image/fetch/$s_!uXvu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfb16a18-811f-4f89-8152-5bfdfa293897_5712x4284.jpeg 848w, https://substackcdn.com/image/fetch/$s_!uXvu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfb16a18-811f-4f89-8152-5bfdfa293897_5712x4284.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!uXvu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfb16a18-811f-4f89-8152-5bfdfa293897_5712x4284.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Getting set up in the room</figcaption></figure></div><p><strong>20:40</strong> - Get all those on-call into a digital meeting room. Assign tasks to everyone - mostly monitoring to begin with. Keep morale up, keep the tone jokey but serious. We all know the gravity of the situation. Inform everyone when the big expected traffic peaks will hit.</p><p><strong>21:02</strong> - Results start coming out. We verify, verify, verify. Is the election API working? Are the widgets displaying correctly?</p><p><strong>21:30</strong> - The editor-in-chief of VG comes to our on-call room with the biggest smile and loudest praise. Also, candy. The director of engineering relays that all the editors-in-chiefs are very pleased.</p><p><strong>22:00</strong> - We take a break. We get out of the room, take a snack, go check on the newsrooms.</p><p><strong>22:50</strong> - The election results are called. Traffic begins to drop. We summarize and head home for the night.</p><p>Our systems are heavily intertwined. These are big systems with long, historical codebases. To prepare we involved people from all possible areas, and made sure there was a plan. A repeated phrase from the newsrooms: &#8220;we have backups for our backups&#8221;. Every backup we had was tested. The newsrooms told us we&#8217;d never been as prepared as we were this year. Good! That&#8217;s how we wanted them to feel.</p><p>Part of being incident commander is managing time and resources. Not only of yourself, but others. This is a high stress scenario. I encouraged people to take breaks, and saved my energy for the election night. As incident commander, my role isn&#8217;t to fix everything. It&#8217;s to guide the efforts, and make sure we don&#8217;t drop the ball. An important philosophy I follow: <em>shut up when smarter people are talking</em>. </p><p>While a lot of things could&#8217;ve gone wrong, they didn&#8217;t. The time and energy we invested into ensuring that we had a good default while also being ready to quickly adapt. These learnings go into our dedication to journalism. It&#8217;s not just the journalists who are dedicated, or the financial operators, or the editor-in-chiefs. It&#8217;s everyone, and it&#8217;s one of the beautiful things that make me proud to work at Schibsted.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/norwegian-elections-and-news-tech?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/norwegian-elections-and-news-tech?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Something I made for myself - hiraeth, gobaith, and derw]]></title><description><![CDATA[There are two personality traits I value highly in myself: the desire to do things correctly, and the desire to be pragmatic.]]></description><link>https://thetechenabler.substack.com/p/something-i-made-for-myself-hiraeth</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/something-i-made-for-myself-hiraeth</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Sat, 06 Sep 2025 14:13:10 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Mj8K!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9de1be99-d567-4370-b984-05d2d10af951_1606x403.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p> There are two personality traits I value highly in myself: the desire to do things correctly, and the desire to be pragmatic.</p><p>Correctness, for me, means code that doesn&#8217;t break. My usual approach to writing hard-to-break code is through good types and good tests. Pragmatic, for me, means code that enables whatever I, my team, or others are trying to accomplish. Pragmatism in code sometimes requires compromise in correctness. If correctness was valued higher than pragmatism, then the industry would be using dependently-typed languages, or those like Elm which promise no runtime errors. We certainly wouldn&#8217;t be using JavaScript or AI-generated code.</p><p>When a large shift towards TypeScript happened, I felt like it had some good compromises between correctness and pragmatism. But it still had lots of gaps.</p><p><em>This post is part of <a href="https://lobste.rs/s/0nstyk/join_lobsters_blog_carnival">Lobste.rs&#8217; blog festival</a>, the prompt is: <strong>What have you made for yourself?</strong></em></p><p>That began my collection of TypeScript libraries, called <a href="https://github.com/eeue56/hiraeth">hiraeth</a>.</p><p>Hiraeth is a Welsh word, meaning a sense of loss, nostalgia, and longing for something that used to be or could've been. I chose this name to reflect my longing for simplicity that I once found in Elm. Elm's still a great language, don't get me wrong, but I simply end up using Typescript in more work projects than I do Elm. So to me, Hiraeth became home-from-home. I have two naming standards for projects: cutesy, Welsh words (e.g <em>bach</em>, <em>coed</em>) as project names when I think the project is novel but better alternatives exist, and to-the point explicit names (e.g ts-core) when I think a project is useful outside of <em>Hiraeth</em>.</p><p><a href="https://github.com/eeue56/bach">Bach</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a> was the first. A lightweight pytest-style testing framework that&#8217;s TypeScript-native. At the time, jest and other similar test runners were heavy, slow, and required `expect(x).to.be(y)` style tests. Bach focused on making it simple and quick to write tests. Something I could drop into any project without too much overhead. Since tests are a big part of my desire for correctness, a good testing framework helps accomplish that. I&#8217;ve add some features when there&#8217;s a proven need for them - async tests, filtering of output, running tests in batches, and snapshot tests. If I had a similar need in 2025, there&#8217;s plenty of alternatives built into Node/Bun. I probably would&#8217;ve never made it. But it&#8217;s been the hiraeth library I use most consistently.</p><p>To help make Bach, I also made <a href="https://github.com/eeue56/ts-assert">ts-assert</a>. ts-assert simply wraps Node&#8217;s assert module with types that enforce both arguments to have the same type.</p><p>I needed a way to represent Maybe and Result types, so I wrote <a href="https://github.com/eeue56/ts-core/">ts-core</a> to provide some of the functional APIs and types that I loved in ML-family languages. There were other big libraries that provided these types, but they tended to include too many features, and too much code, for me to feel comfortable using them. I&#8217;ve mostly stopped using <em>ts-core</em> and tend to just roll my own `<em>Result</em>` type in each project as needed. In TypeScript, I didn&#8217;t use `<em>Result.map</em>` and the other functional programming APIs that much.</p><p>Benchmarking is a natural companion to testing, so I wrote <a href="https://github.com/eeue56/mainc">mainc</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>. <em>mainc</em>&#8217;s focus is to be lightweight, much like <em>bach</em>&#8217;s focus. Writing a good benchmarking engine is pretty difficult to get right though. Getting consistently statically-meaningful data out of benchmarking is a pretty tough problem, and it&#8217;s not one I was planning to solve. So other than for quick estimates, I don&#8217;t use <em>mainc</em>. That&#8217;s a problem that I don&#8217;t have direct knowledge in, and time spent earning that knowledge would&#8217;ve been better spent elsewhere. There&#8217;s lots of other great tools out there that I use for benchmarking - but I&#8217;m very much on the user side of those tools rather than the creator. </p><p>Part of my approach to pragmatism is to focus my energy and time. Too often in the past, I&#8217;d get so distracted by creating a framework or library that I&#8217;d forget what I was actually making it for. Instead of making a game, I&#8217;d make a framework to make games, finishing neither. Instead of writing a blog post, I&#8217;d make a static site generator. These days I do the opposite: start with what I want to achieve, then abstract out any frameworks or libraries that I created along the way. Dropping <em>mainc</em> fits into this philosophy: instead of creating a benchmarking tool, I create the things I want to benchmark instead.</p><p><a href="https://github.com/eeue56/geiriadur">geiriadur</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a> is a documentation generator for TypeScript libraries. I frequently run into JavaScript or TypeScript libraries which completely lack any kind of documentation, and when they do - they make it difficult to jump to the source or see the types. <em>geiriadur</em> gives the raw TypeScript function definition, inlines the jsdoc comment, and gives a link to the source for that specific function. Very handy for working with big, unfamiliar codebases. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Mj8K!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9de1be99-d567-4370-b984-05d2d10af951_1606x403.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Mj8K!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9de1be99-d567-4370-b984-05d2d10af951_1606x403.png 424w, https://substackcdn.com/image/fetch/$s_!Mj8K!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9de1be99-d567-4370-b984-05d2d10af951_1606x403.png 848w, https://substackcdn.com/image/fetch/$s_!Mj8K!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9de1be99-d567-4370-b984-05d2d10af951_1606x403.png 1272w, https://substackcdn.com/image/fetch/$s_!Mj8K!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9de1be99-d567-4370-b984-05d2d10af951_1606x403.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Mj8K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9de1be99-d567-4370-b984-05d2d10af951_1606x403.png" width="1456" height="365" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9de1be99-d567-4370-b984-05d2d10af951_1606x403.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:365,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:43778,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/172333807?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9de1be99-d567-4370-b984-05d2d10af951_1606x403.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Mj8K!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9de1be99-d567-4370-b984-05d2d10af951_1606x403.png 424w, https://substackcdn.com/image/fetch/$s_!Mj8K!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9de1be99-d567-4370-b984-05d2d10af951_1606x403.png 848w, https://substackcdn.com/image/fetch/$s_!Mj8K!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9de1be99-d567-4370-b984-05d2d10af951_1606x403.png 1272w, https://substackcdn.com/image/fetch/$s_!Mj8K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9de1be99-d567-4370-b984-05d2d10af951_1606x403.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><a href="https://github.com/eeue56/coed">coed</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a> is a functional html library backed by a virtual-dom. It&#8217;s the 4th or 5th virtual-dom library I&#8217;ve implemented, but it&#8217;s probably my favourite so far. I&#8217;m not a fan of React, Svelte, Vue, or Angular. If I&#8217;m writing basic html, I&#8217;ll do that as html. But if I&#8217;m making an SPA (a real SPA), I prefer everything to be code. No fancy transpiling or strange configuration tricks, just normal JavaScript function calls. It supports static rendering and hydration. One of the reason I&#8217;m pretty happy with it is because the patching and rendering is relatively to understand. <a href="https://github.com/eeue56/make-your-own-tea/pull/1">This PR</a> shows roughly the step-by-step process to implement a similar virtual-dom algorithm.</p><p><a href="https://github.com/eeue56/adeilad/">adeilad</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a> provides an Elm-style JSON decoding/encoding API for TypeScript. Used in combination with <a href="https://github.com/eeue56/amddiffyn">amddiffyn</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-6" href="#footnote-6" target="_self">6</a>, which can generate <em>adeilad</em> decoders from example JSON, it provides a way to move data from the edges of TypeScript into the fully-typed ecosystem (i.e avoiding <em>JSON.parse(x) as User</em>). <em>adeilad</em> was inspired by my work on Elm&#8217;s decode-pipeline library, and <em>amddiffyn</em> was inspired by my work on json-to-elm.</p><p><a href="https://github.com/eeue56/baner">baner</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-7" href="#footnote-7" target="_self">7</a> is a flag-parsing library. I&#8217;d used <em>yargs</em> a bunch before TypeScript, and I liked the adaptability and simplicity. But once TypeScript became my go-to, I craved a typed alternative. Thus <em>baner</em> was born. While I use <em>baner</em> in a lot of my projects, I&#8217;m not a fan of the API I created for it. The creation of parsers is easy, but using the parsed information is very verbose. I would prefer a typed API that would return a typed tuple. When I get time and motivation, maybe I&#8217;ll do that.</p><p>All these small libraries lead to one destination: <a href="https://github.com/eeue56/derw">Derw</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-8" href="#footnote-8" target="_self">8</a>, my Elm-inspired language with native TypeScript support. <em>Derw</em> is intended as the ultimate solution to my <em>hiraeth</em> - a way to write code in the way I like, with both the correctness to ensure things work, and the pragmatism to get things done. As I increasingly worked with TypeScript codebases, my desire to use an ML-family language while still getting things done felt pretty important.</p><p>Derw was fun to write. Since I already had many of the pieces I needed to create a full stack language, the majority of time initially were spent on writing the compiler instead of libraries. Derw uses almost all of the <em>Hiraeth</em> libraries I&#8217;ve mentioned.</p><p>Derw in a nutshell:</p><ul><li><p>ML-family language (<em>closest inspiration: Elm and Haskell. Next closest: Go and Python</em>)</p></li><li><p>Fullstack, both backend and frontend</p></li><li><p>Majority of the compiler is self-bootstrapping (written in Derw itself)</p></li><li><p>First-class interop with TypeScript and JavaScript</p></li><li><p>Compiles to TypeScript, JavaScript, Derw (itself), and English (for useful error messages).</p></li><li><p>Elm-style virtual-dom <em>html</em> library with server side rendering and hydration (via Coed).</p></li><li><p>Auto-formater (i.e <em>derw format</em>) built-in like Go&#8217;s</p></li><li><p>Testing framework (i.e <em>derw test</em>) built-in (via Bach) much like Go&#8217;s</p></li><li><p>Syntax highlighting</p></li><li><p>LSP integration</p></li><li><p>Git-based package management</p></li><li><p>The compiler (and majority of tooling) works both locally and in the browser</p></li></ul><p>One of the neat pragmatic features of Derw is that I avoid doing too much irreversible optimization. There is very little optimization done on the output of the language itself, instead preferring to optimize the APIs of the libraries it provides. I wanted developers to be able to switch out from Derw at any point they wanted. All the generated TypeScript and JavaScript could be used as a starting point to switch the codebase over to straight TypeScript, reducing the time to rewrite and avoid vendor lock-in. I&#8217;ve evacuated some projects from Derw to straight TypeScript very painlessly. </p><p>When writing a niche language, I was mindful of the fact that 1) few people will use it and 2) they would be annoyed if the project died. Success, to me, was only defined by my personal satisfaction of having made a language that solved some of my pains with Elm, and my pains with TypeScript. If npm is to be believed, derw gets around 20 downloads per month on average. That&#8217;s perfectly fine with me. I don&#8217;t think there&#8217;s an active community using it, that&#8217;s also fine. </p><p>In an alternate reality, Derw would&#8217;ve been the next big thing for functional programmers after Elm. I would be spending my time doing compiler things. But that never happened, and that&#8217;s okay too. The knowledge I&#8217;ve gained from Derw has been insightful. </p><p>While I already knew how to write compilers, Derw took my knowledge to the next level in writing compilers that worked both on-device and in the browser. A good example - how to detach as much I/O from the core compiler while still having a compiler with good performance.</p><p>Generating TypeScript which would be performant, type-safe, and human-readable was an interesting challenge. The biggest lesson I learned: keep the TypeScript types simple, and don&#8217;t try to be too clever. While many of TypeScript&#8217;s utility types are useful, they came with a performance cost for the TypeScript compiler. I probably stuck too closely to keeping things simple though, and as TypeScript&#8217;s gotten faster, I&#8217;ve started to adopt more of the utility types.</p><p><a href="https://github.com/eeue56/gwe">gwe</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-9" href="#footnote-9" target="_self">9</a> is a compile target language I wrote with the intention of compiling Derw to WebAssembly. <em>gwe</em> is intentionally written as an intermidatery between immutable ML-family languages and WebAssembly. I&#8217;d been wanting to write something big in Rust and WebAssembly for a while, and it seemed like a natural fit for this. It&#8217;s not fully finished - life got busy, and <em>gwe</em> become lower priority than the other things I was doing. From a Rust perspective, <em>gwe </em>is a very beginner project. </p><p><a href="https://github.com/eeue56/jump-to">jump-to</a> is a vimium-style navigation tool for Chrome. I used to use vimium a bunch to minimize the amount of time my hands were away from the keyboard, but I couldn&#8217;t find a Chrome Extension made by a provider I trusted. I generally don&#8217;t use Chrome Extensions unless I&#8217;ve fully verified who made it. It&#8217;s often easier to make my own Chrome extension, plus it gives me a reason to learn how they work. </p><p><a href="https://github.com/eeue56/gweld">gweld</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-10" href="#footnote-10" target="_self">10</a> is a <em>python http.server</em> inspired dev-server with live-reload. I made it after being dismayed at the amount of code that the majority of popular live-reload dev servers used, and needed a way to stream video files as chunks. It uses only the built-in Node standard library. A big part of my <em>hiraeth </em>is the desire for straightforward low-code solutions to common problems.</p><p><a href="https://github.com/eeue56/amser">amser</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-11" href="#footnote-11" target="_self">11</a> is a opinionated simple way to keep track of projects changed during a session. Since I have a lot of different projects when I&#8217;m doing hobby code, I needed some kind of idea how I split my time between them. Like <em>gweld</em>, <em>amser </em>uses only the Node standard library.</p><p><a href="https://github.com/eeue56/gobaith">gobaith</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-12" href="#footnote-12" target="_self">12</a> is a mental health tracker I originally built for myself, and didn&#8217;t open source. While I usually release things as open source by default, I avoided it with <em>gobaith</em>. I was not in the mental state to support others, and I needed something that very specifically helped me with my mental health issues. It had been my plan for years to publicly release it, but the thought of being responsible for writing code that took good care of a user&#8217;s personal mental health data was intimidating. I delayed releasing it, month after month. Eventually after meeting some others with the same condition, in the same place where I had been years ago, I decided I should release it. For them. So that I could at least help a little with their recovery journey.</p><p>I had two main concerns before release: </p><ol><li><p>How do I make something they&#8217;ll actually use? </p></li><li><p>How do I ensure it&#8217;s robust enough to succeed?</p></li></ol><p>I sat down with my fellow sufferers, and listened to what they needed. I read paper after paper on trends, behaviours, and patterns on our conditions. We drew things together, we discussed research papers and therapy techniques. In the end, I combined what I knew worked for me with the insights from my friends. I couldn&#8217;t make it work for everyone, but I could make it work for <em>people like me</em>, and give others the keys needed to adapt it for their needs.</p><p>A robust tracker needs to avoid data loss at all costs. Since the data lives only on user devices, I needed to ensure that any updates wouldn&#8217;t cause them to accidentally lose their data. <em>gobaith</em> is very forgiving - each migration of the data store avoids any actions that might lose data, providing logs if the migration would fail. <em>gobaith</em> works in the browser, in Electron, or as an app on Android. The test suite via Playwright runs on all three platforms, helping to keep features in-sync. The data can be stored either in IndexedDB, a server-based backend, or both. The test suite is data-storage agnostic too.</p><p>I&#8217;ve rewritten <em>gobaith</em>&#8217;s rendering layer a few times. The first version, which I built only for myself, was pretty messy. Lots of DOM manipulation, no TypeScript. The second rewrite switched over to a frameworkless model-view-update (MVU) approach I sometimes use: every view function returns both the html body as a string, and event handlers to attach to the DOM, enforced through types and the API. While that frameworkless approach is actually pretty good performance-wise, it&#8217;s not ideal for maintenance. In the third rewrite, I switched it all over to use my <em>coed</em> library. Way easier to maintain, and avoid little errors like misspelled tag names.  </p><p>The latest big thing I&#8217;ve done with <em>gobaith</em> is to prepare it for an Google Play store release. As Google is going to make it harder to side-load apps, I figured I should just put <em>gobaith</em> on the Play Store. Unfortunately, that costs money, and I&#8217;m already making a loss from releasing it. I&#8217;ll have the <em>gobaith</em> app at some low one-time fee, like $3, to help cover some of the costs of development. All the code will always be open source and available for people to use and build themselves, and I&#8217;ll give free keys to anyone who wants the Google Play store version but can&#8217;t afford it. My goal isn&#8217;t to make money, but to avoid losses. I also have <a href="https://github.com/sponsors/eeue56">Github sponsors enabled</a> for that same reason: it&#8217;s costly, both in terms of time and resources, to develop open source things for others.</p><p>Games are something I left out, but I&#8217;ve made a lot of little games for myself too. Pico8 has been my tool of choice, often making visualizations or novel experiences. <a href="https://eeue56.github.io/pico8-games/psychotris/">Psychotris</a> is intended to finally answer the question on everyone&#8217;s mind: <em>what would Tetris be like if you had psychosis and hallucinations?</em> It starts out pretty normal, but the visual effects quickly ramp up.</p><p>Some others, a Baba Is You clone:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iVU1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20052d6f-f707-468d-886f-8e0bf9ef131f_1279x1224.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iVU1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20052d6f-f707-468d-886f-8e0bf9ef131f_1279x1224.png 424w, https://substackcdn.com/image/fetch/$s_!iVU1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20052d6f-f707-468d-886f-8e0bf9ef131f_1279x1224.png 848w, https://substackcdn.com/image/fetch/$s_!iVU1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20052d6f-f707-468d-886f-8e0bf9ef131f_1279x1224.png 1272w, https://substackcdn.com/image/fetch/$s_!iVU1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20052d6f-f707-468d-886f-8e0bf9ef131f_1279x1224.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iVU1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20052d6f-f707-468d-886f-8e0bf9ef131f_1279x1224.png" width="197" height="188.5285379202502" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/20052d6f-f707-468d-886f-8e0bf9ef131f_1279x1224.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1224,&quot;width&quot;:1279,&quot;resizeWidth&quot;:197,&quot;bytes&quot;:33483,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/172333807?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20052d6f-f707-468d-886f-8e0bf9ef131f_1279x1224.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!iVU1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20052d6f-f707-468d-886f-8e0bf9ef131f_1279x1224.png 424w, https://substackcdn.com/image/fetch/$s_!iVU1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20052d6f-f707-468d-886f-8e0bf9ef131f_1279x1224.png 848w, https://substackcdn.com/image/fetch/$s_!iVU1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20052d6f-f707-468d-886f-8e0bf9ef131f_1279x1224.png 1272w, https://substackcdn.com/image/fetch/$s_!iVU1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F20052d6f-f707-468d-886f-8e0bf9ef131f_1279x1224.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3CW-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0be2f57d-d9ee-4b5e-b05b-449fb9306f06_1279x1224.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3CW-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0be2f57d-d9ee-4b5e-b05b-449fb9306f06_1279x1224.png 424w, https://substackcdn.com/image/fetch/$s_!3CW-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0be2f57d-d9ee-4b5e-b05b-449fb9306f06_1279x1224.png 848w, https://substackcdn.com/image/fetch/$s_!3CW-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0be2f57d-d9ee-4b5e-b05b-449fb9306f06_1279x1224.png 1272w, https://substackcdn.com/image/fetch/$s_!3CW-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0be2f57d-d9ee-4b5e-b05b-449fb9306f06_1279x1224.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3CW-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0be2f57d-d9ee-4b5e-b05b-449fb9306f06_1279x1224.png" width="190" height="181.8295543393276" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0be2f57d-d9ee-4b5e-b05b-449fb9306f06_1279x1224.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1224,&quot;width&quot;:1279,&quot;resizeWidth&quot;:190,&quot;bytes&quot;:32633,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/172333807?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0be2f57d-d9ee-4b5e-b05b-449fb9306f06_1279x1224.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!3CW-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0be2f57d-d9ee-4b5e-b05b-449fb9306f06_1279x1224.png 424w, https://substackcdn.com/image/fetch/$s_!3CW-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0be2f57d-d9ee-4b5e-b05b-449fb9306f06_1279x1224.png 848w, https://substackcdn.com/image/fetch/$s_!3CW-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0be2f57d-d9ee-4b5e-b05b-449fb9306f06_1279x1224.png 1272w, https://substackcdn.com/image/fetch/$s_!3CW-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0be2f57d-d9ee-4b5e-b05b-449fb9306f06_1279x1224.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>A depression/anxiety/mania simulator:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VRQ5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F316bf945-488b-41f2-9f4b-d4ae4ba996b4_1279x1224.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VRQ5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F316bf945-488b-41f2-9f4b-d4ae4ba996b4_1279x1224.png 424w, https://substackcdn.com/image/fetch/$s_!VRQ5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F316bf945-488b-41f2-9f4b-d4ae4ba996b4_1279x1224.png 848w, https://substackcdn.com/image/fetch/$s_!VRQ5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F316bf945-488b-41f2-9f4b-d4ae4ba996b4_1279x1224.png 1272w, https://substackcdn.com/image/fetch/$s_!VRQ5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F316bf945-488b-41f2-9f4b-d4ae4ba996b4_1279x1224.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VRQ5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F316bf945-488b-41f2-9f4b-d4ae4ba996b4_1279x1224.png" width="281" height="268.91634089132134" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/316bf945-488b-41f2-9f4b-d4ae4ba996b4_1279x1224.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1224,&quot;width&quot;:1279,&quot;resizeWidth&quot;:281,&quot;bytes&quot;:42895,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/172333807?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F316bf945-488b-41f2-9f4b-d4ae4ba996b4_1279x1224.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!VRQ5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F316bf945-488b-41f2-9f4b-d4ae4ba996b4_1279x1224.png 424w, https://substackcdn.com/image/fetch/$s_!VRQ5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F316bf945-488b-41f2-9f4b-d4ae4ba996b4_1279x1224.png 848w, https://substackcdn.com/image/fetch/$s_!VRQ5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F316bf945-488b-41f2-9f4b-d4ae4ba996b4_1279x1224.png 1272w, https://substackcdn.com/image/fetch/$s_!VRQ5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F316bf945-488b-41f2-9f4b-d4ae4ba996b4_1279x1224.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>As a final reflection, I realized while writing this that I spend a <em>lot</em> of time making things for myself. I release them for others to use, sure, but I usually have 0 ambitions of actually getting others to use them. In the past, when I was active in the Elm community, it was the opposite. json-to-elm, elm-html-in-html, elm-html-test, server side Elm were all things I made intentionally for others to use. Maintaining those, especially when I moved away from Elm, became a chore. Something I didn&#8217;t enjoy doing, and something I didn&#8217;t really get any kind of return on. These days, I&#8217;m happy watering my plants in my open-source garden. I trim some leaves, and if others would like to take a look, they&#8217;re welcome to. I hope you enjoyed reading about my garden!</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/something-i-made-for-myself-hiraeth?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/something-i-made-for-myself-hiraeth?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>bach: &#8220;small&#8221;, or &#8220;little&#8221;. I feel many test frameworks have too many features, or too much noise. <em>bach</em> is intended to be a small framework.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>mainc<em>: &#8220;</em>bench&#8221;, or &#8220;plank&#8221;. </p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p>geiriadur: &#8220;dictionary&#8221;. Docs are kinda like a dictionary for translating code into human-understandable things.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p>coed: &#8220;wood&#8221;, or &#8220;tree&#8221;. <em>coed</em> builds trees of html nodes. </p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-5" href="#footnote-anchor-5" class="footnote-number" contenteditable="false" target="_self">5</a><div class="footnote-content"><p>adeilad: &#8220;building&#8221;. A way of composing things together - the boundary of type safe code in TypeScript with unsafe data from APIs and input. </p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-6" href="#footnote-anchor-6" class="footnote-number" contenteditable="false" target="_self">6</a><div class="footnote-content"><p>amddiffyn: &#8220;defend&#8221;. Defend the code from the data by using the correct type definitions.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-7" href="#footnote-anchor-7" class="footnote-number" contenteditable="false" target="_self">7</a><div class="footnote-content"><p>baner: &#8220;flag&#8221;. It takes flags and parses them.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-8" href="#footnote-anchor-8" class="footnote-number" contenteditable="false" target="_self">8</a><div class="footnote-content"><p>derw: &#8220;oak&#8221;. Paying homage to the inspiration of Elm, much like the other tree-named languages that came after Elm.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-9" href="#footnote-anchor-9" class="footnote-number" contenteditable="false" target="_self">9</a><div class="footnote-content"><p>gwe: &#8220;web&#8221;. It targets WebAssembly.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-10" href="#footnote-anchor-10" class="footnote-number" contenteditable="false" target="_self">10</a><div class="footnote-content"><p>gweld: &#8220;watch&#8221;, or &#8220;to look at&#8221;. It watches files.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-11" href="#footnote-anchor-11" class="footnote-number" contenteditable="false" target="_self">11</a><div class="footnote-content"><p>amser: &#8220;time&#8221;. It helps me manage my time.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-12" href="#footnote-anchor-12" class="footnote-number" contenteditable="false" target="_self">12</a><div class="footnote-content"><p>gobaith: &#8220;hope&#8221;. It brought me hope, and I hope it does for others too.</p></div></div>]]></content:encoded></item><item><title><![CDATA[Gut-feelings vs metrics]]></title><description><![CDATA[Often as developers, we spend too much time in blacks and whites. We assume too much. Developers often want things to fit in perfectly neat boxes. Python is the best for x, WebStorm is the best for y. But the real world doesn&#8217;t fit into nice boxes.]]></description><link>https://thetechenabler.substack.com/p/gut-feelings-vs-metrics</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/gut-feelings-vs-metrics</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Tue, 05 Aug 2025 06:59:02 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/6bcb4489-c84d-40eb-8d23-9905cd887175_1024x685.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Often as developers, we spend too much time in blacks and whites. We assume too much<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>. Developers often want things to fit in perfectly neat boxes. Python is the best for <em>x</em>, WebStorm is the best for <em>y</em>. Everyone has a bias towards what they&#8217;re familiar with<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>. But the real world doesn&#8217;t fit into nice boxes. There&#8217;s chaos and mess everywhere, and approaches that ignore the chaos often tend to fail. </p><p>Some choices in software development come down to personal preferences. Is there an objective measure for which editor is the best? Is there an objective measure for which language is the most enjoyable? Not so much. Most papers I&#8217;ve read which attempt to measure these qualities struggle with defining good metrics. Other choices have data to back them up. How many deploys have happened in the last week? How quickly were incidents resolved? </p><p>As an enabler, I often have to use both perspectives to shape discussions. The quantitative (data) vs qualitative (experiences) mindset is something drilled into UX research<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a> work. Numbers don&#8217;t tell the full story, while experiences could just be anecdotes. Combining both is an important factor in behaviour analysis and change, which is why I prefer to combine both. Measure for raw data, collect experiences to shape an opinion.</p><p>To give an example from the news industry, we have many metrics that measure the success of an article. Typically that would be clicks, completion rate, and the number of shares. Once those are combined with the demographics of users, it can give a sense of success. However, it&#8217;s only a partial story. For example: short clickbait titles where the body text is only 2 paragraphs would result in high clicks and completion rate, but would harm the user&#8217;s overall opinion of the news site. There is no metric that can measure at scale &#8220;how did you feel about this article?&#8221;. <strong>We can make approximations, but they&#8217;re numbers to fit a trend rather than understanding the reasons for the trend.</strong> </p><p>Let&#8217;s say we track the number of users who keep coming back to the clickbait articles - if they don&#8217;t like it, the weekly active users should drop right? But there&#8217;s many factors that could impact that metric. Adverts, subscriptions prices, traffic source, the content topic itself, the thumbnail used, whether the reader has an emotional attachment to the topic, etc. <strong>Too many variables make it hard to assess, and too much &#8220;human&#8221; makes the insight only measure what they do, not why they did it.</strong></p><p>At the same time, <strong>people are bad at expressing themselves</strong>. It&#8217;s hard collect accurate user assessments of what they&#8217;ve done. They forget things, or they&#8217;re unable to provide insight into why they did or didn&#8217;t do something. Often they&#8217;ll believe they did things that they didn&#8217;t. </p><p>These are the exact same problems I face when shaping an opinion that represents a collective - both at my day job, and in my volunteering role as the leader of Tekna's Network for Developers. </p><p>I don&#8217;t have an objectively correct solution to solve this problem, but here&#8217;s how I approach mixing experience-gathering with data-gathering:</p><ol><li><p>Don&#8217;t be afraid to admit what you don&#8217;t know. There are big pockets of empty space in my knowledge - they won&#8217;t get filled if I&#8217;m not willing to listen to others. I don&#8217;t particularly care about me being personally right. I care about things being done well. If it&#8217;s not my way of doing things, that&#8217;s usually fine<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a>.</p></li><li><p>Reflect on my own opinions. Why do I have them? Where did they come from? What would cause me to change my opinions? Are my opinions valid, or something I can&#8217;t justify?</p></li><li><p>Empathy. Understand and listen to others. Let others share their opinions without judgement. The more others trust me, the easier it is to have a good understanding of what they believe, and why they believe it.</p></li><li><p>To figure out difficult problems, there has to be chaos. Chaos can be uncertainty, unclarity, or unknowns. Any difficult problem will have things that could be unknown unknowns. Share little views into this chaos with others. Ask questions about difficult topics to a wider audience. The insight that others can provide often reduces the unknowns. At the same time, don&#8217;t introduce too much chaos. It&#8217;s tiring for others, and it can be damaging. My job involves often finding sense in chaos - it&#8217;s something I enjoy and I&#8217;m good at. But not everyone enjoys that<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a>. Keep it to limited subsets of chaos where you need input from others.</p></li><li><p>Identify the qualities that can have metrics, and gather as much metrics as possible. Challenge your assumptions - don&#8217;t settle for the first metric that seems to prove an opinion right. A diversified combination of sources leads to a richer understanding of trends in data.</p></li><li><p>Don&#8217;t be afraid to challenge opinions. Both your own, and others&#8217;. If you approach it with both empathy and good intentions, others will respond well. It helps when you admit to questioning for sake of debate, rather than disagreeing to form an argument. Be vocal about your own opinion, but in the right settings. Opinions form debates - debates are incredibly important for behaviour change. My worst nightmare is a team of people working together who can&#8217;t have productive disagreements.</p></li><li><p>One data point is not enough to form an opinion on. If people&#8217;s experiences could be an anecdote, so can one data point. If you want to make a claim, back it up with as much data as you can.</p></li><li><p>Metrics shouldn&#8217;t be goals, but they can inform what to set as goals.</p></li><li><p>Sometimes, you have to just trust your gut. Generalisations simplify the process of talking about a problem. There&#8217;s a line between being too general and being too specific. Sometimes you should say &#8220;based on what I know and feel, this is what I believe&#8221;. An opinion shapes direction - but don&#8217;t be afraid to change both your opinion and direction when more data and experiences comes available to you. </p></li></ol><p>A mix of data and opinions make my role easier. It takes time to establish both the collection of data and experiences, but I think it makes my input richer. I could do everything based on my own personal gut-feeling, but I&#8217;d probably make assumptions for a lot of decisions that weren&#8217;t accurate.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/gut-feelings-vs-metrics?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/gut-feelings-vs-metrics?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>This is also an assumption, based on my personal experiences in the tech world for around 2 decades. Meta, right?</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>Fear, uncertainty, and doubt cause a reluctance towards the unknown. Why use Rust when you&#8217;ve never hit a memory safety issue in C++? Is it worth spending time learning and changing a codebase when it&#8217;s unclear what benefit it might have?</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p>Protip: if you want to understand how to approach experience-gathering, sit with some UX researchers for a while. I&#8217;ve been lucky in having close colleagues and friends who helped me understand how to really gain insight from user interviews.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p>There are some hardlines for me though, where it&#8217;ll be hard for me to keep my bias in-check. Being selective in the areas where I let bias show works quite well.  I can excuse myself from discussions, or openly state my personal bias.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-5" href="#footnote-anchor-5" class="footnote-number" contenteditable="false" target="_self">5</a><div class="footnote-content"><p>Sometimes I get feedback like &#8220;<em>x</em> could&#8217;ve been done differently because <em>y</em>&#8221;, and quite often &#8220;<em>y</em>&#8221; was the whole intention. It takes a lot of work to introduce chaos in a structured way. Much like a self-organized audience unconference, there&#8217;s a lot of work that goes into helping others find meaning in chaos.</p><p></p></div></div>]]></content:encoded></item><item><title><![CDATA[Reviewing a journalistic vibe-coded application]]></title><description><![CDATA[How easily could we run vibe-coded applications in production in a news company?]]></description><link>https://thetechenabler.substack.com/p/reviewing-a-journalistic-vibe-coded</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/reviewing-a-journalistic-vibe-coded</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Mon, 28 Jul 2025 10:52:54 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!w9VS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cef6c6-99a5-4197-9eca-8352499d67d9_771x1188.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>How easily could we run vibe-coded applications in production in a news company? To explore this idea, I got Claude Code to create a simple calculator for Oslo's public transport ticket prices. These kinds of small projects are common within journalism, created by journalists who can code which we typically call "editorial developers".</p><p>You can <strong><a href="https://ruter.digital-citizen.no/">try it out here</a></strong>. Here's a screenshot of it running:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!w9VS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cef6c6-99a5-4197-9eca-8352499d67d9_771x1188.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!w9VS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cef6c6-99a5-4197-9eca-8352499d67d9_771x1188.png 424w, https://substackcdn.com/image/fetch/$s_!w9VS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cef6c6-99a5-4197-9eca-8352499d67d9_771x1188.png 848w, https://substackcdn.com/image/fetch/$s_!w9VS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cef6c6-99a5-4197-9eca-8352499d67d9_771x1188.png 1272w, https://substackcdn.com/image/fetch/$s_!w9VS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cef6c6-99a5-4197-9eca-8352499d67d9_771x1188.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!w9VS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cef6c6-99a5-4197-9eca-8352499d67d9_771x1188.png" width="341" height="525.431906614786" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/04cef6c6-99a5-4197-9eca-8352499d67d9_771x1188.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1188,&quot;width&quot;:771,&quot;resizeWidth&quot;:341,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Article content&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Article content" title="Article content" srcset="https://substackcdn.com/image/fetch/$s_!w9VS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cef6c6-99a5-4197-9eca-8352499d67d9_771x1188.png 424w, https://substackcdn.com/image/fetch/$s_!w9VS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cef6c6-99a5-4197-9eca-8352499d67d9_771x1188.png 848w, https://substackcdn.com/image/fetch/$s_!w9VS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cef6c6-99a5-4197-9eca-8352499d67d9_771x1188.png 1272w, https://substackcdn.com/image/fetch/$s_!w9VS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cef6c6-99a5-4197-9eca-8352499d67d9_771x1188.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3><strong>Some context for non-Norwegians</strong></h3><p>Ruter is the public transport company for Oslo and the surrounding areas. While they have always had period tickets (especially for students), they introduced a discount format based on usage in the last couple of years (Reis). Reis provides an increasing discount for each travel you make within a rolling 30 day period. The highest discount it provides is 40%.</p><p>Ruter has faced criticism in recent years due to high costs and aggressive ticket checks. A tool like this allows people to make informed decisions when buying tickets, something which I've been personally missing for a while.</p><h3><strong>Reviewing the code</strong></h3><p>I didn't read any of the code until I'd gotten the prototype working, replicating the expected workflow of non-technical people. I avoided giving any instructions that mentioned technical details. The prompts I used were prompts I'd expect a non-technical person who was familiar with generative AI to write.</p><p><strong><a href="https://github.com/eeue56/ruter-calculator/pull/1">The full review can be found as a pull-request on Github, but I left a lot of comments - approx 41</a></strong>. I tried to review it as if it was created by a human, but I sometimes found myself writing a comment if I was talking to AI, which weirdly uses wording question their decision (e.g "why did you do this?" instead of "why is x like y?"). Here are some of the most relevant comments.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xyqK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86fe845b-a3f2-4cd6-9536-eb3faf4385ec_1213x547.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xyqK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86fe845b-a3f2-4cd6-9536-eb3faf4385ec_1213x547.png 424w, https://substackcdn.com/image/fetch/$s_!xyqK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86fe845b-a3f2-4cd6-9536-eb3faf4385ec_1213x547.png 848w, https://substackcdn.com/image/fetch/$s_!xyqK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86fe845b-a3f2-4cd6-9536-eb3faf4385ec_1213x547.png 1272w, https://substackcdn.com/image/fetch/$s_!xyqK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86fe845b-a3f2-4cd6-9536-eb3faf4385ec_1213x547.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xyqK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86fe845b-a3f2-4cd6-9536-eb3faf4385ec_1213x547.png" width="1213" height="547" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/86fe845b-a3f2-4cd6-9536-eb3faf4385ec_1213x547.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:547,&quot;width&quot;:1213,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Article content&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Article content" title="Article content" srcset="https://substackcdn.com/image/fetch/$s_!xyqK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86fe845b-a3f2-4cd6-9536-eb3faf4385ec_1213x547.png 424w, https://substackcdn.com/image/fetch/$s_!xyqK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86fe845b-a3f2-4cd6-9536-eb3faf4385ec_1213x547.png 848w, https://substackcdn.com/image/fetch/$s_!xyqK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86fe845b-a3f2-4cd6-9536-eb3faf4385ec_1213x547.png 1272w, https://substackcdn.com/image/fetch/$s_!xyqK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F86fe845b-a3f2-4cd6-9536-eb3faf4385ec_1213x547.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">AI's use of language sometimes introduces uncertainty in it's wording: not good for journalistic content.</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CvV1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e1bfa67-b07d-4d7f-b938-06f0675dd84c_1213x843.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CvV1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e1bfa67-b07d-4d7f-b938-06f0675dd84c_1213x843.png 424w, https://substackcdn.com/image/fetch/$s_!CvV1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e1bfa67-b07d-4d7f-b938-06f0675dd84c_1213x843.png 848w, https://substackcdn.com/image/fetch/$s_!CvV1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e1bfa67-b07d-4d7f-b938-06f0675dd84c_1213x843.png 1272w, https://substackcdn.com/image/fetch/$s_!CvV1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e1bfa67-b07d-4d7f-b938-06f0675dd84c_1213x843.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CvV1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e1bfa67-b07d-4d7f-b938-06f0675dd84c_1213x843.png" width="1213" height="843" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9e1bfa67-b07d-4d7f-b938-06f0675dd84c_1213x843.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:843,&quot;width&quot;:1213,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Article content&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Article content" title="Article content" srcset="https://substackcdn.com/image/fetch/$s_!CvV1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e1bfa67-b07d-4d7f-b938-06f0675dd84c_1213x843.png 424w, https://substackcdn.com/image/fetch/$s_!CvV1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e1bfa67-b07d-4d7f-b938-06f0675dd84c_1213x843.png 848w, https://substackcdn.com/image/fetch/$s_!CvV1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e1bfa67-b07d-4d7f-b938-06f0675dd84c_1213x843.png 1272w, https://substackcdn.com/image/fetch/$s_!CvV1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e1bfa67-b07d-4d7f-b938-06f0675dd84c_1213x843.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The AI wrote a lot of brittle code - things that could easily break when making future changes</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9oI9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ee30b0-1bdd-4e23-ae71-c368fb04b312_1213x617.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9oI9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ee30b0-1bdd-4e23-ae71-c368fb04b312_1213x617.png 424w, https://substackcdn.com/image/fetch/$s_!9oI9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ee30b0-1bdd-4e23-ae71-c368fb04b312_1213x617.png 848w, https://substackcdn.com/image/fetch/$s_!9oI9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ee30b0-1bdd-4e23-ae71-c368fb04b312_1213x617.png 1272w, https://substackcdn.com/image/fetch/$s_!9oI9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ee30b0-1bdd-4e23-ae71-c368fb04b312_1213x617.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9oI9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ee30b0-1bdd-4e23-ae71-c368fb04b312_1213x617.png" width="1213" height="617" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/93ee30b0-1bdd-4e23-ae71-c368fb04b312_1213x617.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:617,&quot;width&quot;:1213,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Article content&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Article content" title="Article content" srcset="https://substackcdn.com/image/fetch/$s_!9oI9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ee30b0-1bdd-4e23-ae71-c368fb04b312_1213x617.png 424w, https://substackcdn.com/image/fetch/$s_!9oI9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ee30b0-1bdd-4e23-ae71-c368fb04b312_1213x617.png 848w, https://substackcdn.com/image/fetch/$s_!9oI9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ee30b0-1bdd-4e23-ae71-c368fb04b312_1213x617.png 1272w, https://substackcdn.com/image/fetch/$s_!9oI9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ee30b0-1bdd-4e23-ae71-c368fb04b312_1213x617.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Much like a junior developer, AI writes code in a way that puts way too much faith in the ability of future development to keep contracts that aren't enforced by types or asserts.</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mucF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e865820-1d85-4af8-a6b6-e19f733283ba_1231x870.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mucF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e865820-1d85-4af8-a6b6-e19f733283ba_1231x870.png 424w, https://substackcdn.com/image/fetch/$s_!mucF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e865820-1d85-4af8-a6b6-e19f733283ba_1231x870.png 848w, https://substackcdn.com/image/fetch/$s_!mucF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e865820-1d85-4af8-a6b6-e19f733283ba_1231x870.png 1272w, https://substackcdn.com/image/fetch/$s_!mucF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e865820-1d85-4af8-a6b6-e19f733283ba_1231x870.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mucF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e865820-1d85-4af8-a6b6-e19f733283ba_1231x870.png" width="1231" height="870" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4e865820-1d85-4af8-a6b6-e19f733283ba_1231x870.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:870,&quot;width&quot;:1231,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Article content&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Article content" title="Article content" srcset="https://substackcdn.com/image/fetch/$s_!mucF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e865820-1d85-4af8-a6b6-e19f733283ba_1231x870.png 424w, https://substackcdn.com/image/fetch/$s_!mucF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e865820-1d85-4af8-a6b6-e19f733283ba_1231x870.png 848w, https://substackcdn.com/image/fetch/$s_!mucF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e865820-1d85-4af8-a6b6-e19f733283ba_1231x870.png 1272w, https://substackcdn.com/image/fetch/$s_!mucF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e865820-1d85-4af8-a6b6-e19f733283ba_1231x870.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The AI repeats code frequently and often, even when it's defined helper functions.</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!S2w9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c2db305-4c0b-4d64-abd9-42dfc7b5d894_1213x812.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!S2w9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c2db305-4c0b-4d64-abd9-42dfc7b5d894_1213x812.png 424w, https://substackcdn.com/image/fetch/$s_!S2w9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c2db305-4c0b-4d64-abd9-42dfc7b5d894_1213x812.png 848w, https://substackcdn.com/image/fetch/$s_!S2w9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c2db305-4c0b-4d64-abd9-42dfc7b5d894_1213x812.png 1272w, https://substackcdn.com/image/fetch/$s_!S2w9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c2db305-4c0b-4d64-abd9-42dfc7b5d894_1213x812.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!S2w9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c2db305-4c0b-4d64-abd9-42dfc7b5d894_1213x812.png" width="1213" height="812" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9c2db305-4c0b-4d64-abd9-42dfc7b5d894_1213x812.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:812,&quot;width&quot;:1213,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Article content&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Article content" title="Article content" srcset="https://substackcdn.com/image/fetch/$s_!S2w9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c2db305-4c0b-4d64-abd9-42dfc7b5d894_1213x812.png 424w, https://substackcdn.com/image/fetch/$s_!S2w9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c2db305-4c0b-4d64-abd9-42dfc7b5d894_1213x812.png 848w, https://substackcdn.com/image/fetch/$s_!S2w9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c2db305-4c0b-4d64-abd9-42dfc7b5d894_1213x812.png 1272w, https://substackcdn.com/image/fetch/$s_!S2w9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c2db305-4c0b-4d64-abd9-42dfc7b5d894_1213x812.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The AI hallucinates a lot, so it took a considerable amount of time and effort from me to fact-check the AI's numbers, despite the fact I provided the AI with the pages needed to get the correct numbers.</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8nag!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F126a0da6-72d2-4312-9545-88b575879716_1219x919.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8nag!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F126a0da6-72d2-4312-9545-88b575879716_1219x919.png 424w, https://substackcdn.com/image/fetch/$s_!8nag!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F126a0da6-72d2-4312-9545-88b575879716_1219x919.png 848w, https://substackcdn.com/image/fetch/$s_!8nag!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F126a0da6-72d2-4312-9545-88b575879716_1219x919.png 1272w, https://substackcdn.com/image/fetch/$s_!8nag!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F126a0da6-72d2-4312-9545-88b575879716_1219x919.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8nag!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F126a0da6-72d2-4312-9545-88b575879716_1219x919.png" width="1219" height="919" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/126a0da6-72d2-4312-9545-88b575879716_1219x919.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:919,&quot;width&quot;:1219,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Article content&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Article content" title="Article content" srcset="https://substackcdn.com/image/fetch/$s_!8nag!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F126a0da6-72d2-4312-9545-88b575879716_1219x919.png 424w, https://substackcdn.com/image/fetch/$s_!8nag!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F126a0da6-72d2-4312-9545-88b575879716_1219x919.png 848w, https://substackcdn.com/image/fetch/$s_!8nag!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F126a0da6-72d2-4312-9545-88b575879716_1219x919.png 1272w, https://substackcdn.com/image/fetch/$s_!8nag!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F126a0da6-72d2-4312-9545-88b575879716_1219x919.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">In places, the AI makes assumptions on how the user would do things. In some cases, it leads to good UX, but in other cases it would lead to worse or misleading UX</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!M9N_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc05c01-01c2-4dcb-b211-400dd959bfd7_1362x514.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!M9N_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc05c01-01c2-4dcb-b211-400dd959bfd7_1362x514.png 424w, https://substackcdn.com/image/fetch/$s_!M9N_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc05c01-01c2-4dcb-b211-400dd959bfd7_1362x514.png 848w, https://substackcdn.com/image/fetch/$s_!M9N_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc05c01-01c2-4dcb-b211-400dd959bfd7_1362x514.png 1272w, https://substackcdn.com/image/fetch/$s_!M9N_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc05c01-01c2-4dcb-b211-400dd959bfd7_1362x514.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!M9N_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc05c01-01c2-4dcb-b211-400dd959bfd7_1362x514.png" width="1362" height="514" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0fc05c01-01c2-4dcb-b211-400dd959bfd7_1362x514.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:514,&quot;width&quot;:1362,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Article content&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Article content" title="Article content" srcset="https://substackcdn.com/image/fetch/$s_!M9N_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc05c01-01c2-4dcb-b211-400dd959bfd7_1362x514.png 424w, https://substackcdn.com/image/fetch/$s_!M9N_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc05c01-01c2-4dcb-b211-400dd959bfd7_1362x514.png 848w, https://substackcdn.com/image/fetch/$s_!M9N_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc05c01-01c2-4dcb-b211-400dd959bfd7_1362x514.png 1272w, https://substackcdn.com/image/fetch/$s_!M9N_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fc05c01-01c2-4dcb-b211-400dd959bfd7_1362x514.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Overall, I was not happy to run the code in production. But it was mostly small things that I could've got the AI to change, or correct manually myself.</figcaption></figure></div><p>The code wasn't bad quality, but the parts that contained logic were hard to read - a combination of poor variable names, weird loops, a lack of types, and a lack of comments. The AI had hallucinated a bunch of data, which is kinda to be expected from generative AI. I hoped for better, though. Once I explicitly provided the correct data without relying on the AI to read the webpage, it corrected the data. My main concern would be the factual correctness of the web page. It seems like a review step from a new AI context might've helped.</p><p>I think I could change the system prompt to ensure:</p><ul><li><p>Code has some form of type checking (either TypeScript, or jsdoc types)</p></li><li><p>Avoid creating unnecessary structures (e.g weird while loops, a class that didn't need to be a class)</p></li><li><p>Enforcement of contracts across function barriers</p></li></ul><p>Either way, it took me about 30 minutes to go from idea to a working prototype. Another hour to review and correct the mistakes AI had made, but all considerably less time than a human developer would've taken. For journalism, the incorrect usage of facts means we need to manually review every data point the app uses. That will take a considerable amount of extra time - though for prototyping an idea, it&#8217;s good. </p><p>The journey of a vibe coded journalistic app from idea to production probably would look something like this:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GARV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10f54ff-19a6-4e44-bea3-0928fb58d098_1200x742.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GARV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10f54ff-19a6-4e44-bea3-0928fb58d098_1200x742.png 424w, https://substackcdn.com/image/fetch/$s_!GARV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10f54ff-19a6-4e44-bea3-0928fb58d098_1200x742.png 848w, https://substackcdn.com/image/fetch/$s_!GARV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10f54ff-19a6-4e44-bea3-0928fb58d098_1200x742.png 1272w, https://substackcdn.com/image/fetch/$s_!GARV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10f54ff-19a6-4e44-bea3-0928fb58d098_1200x742.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GARV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10f54ff-19a6-4e44-bea3-0928fb58d098_1200x742.png" width="1200" height="742" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d10f54ff-19a6-4e44-bea3-0928fb58d098_1200x742.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:742,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GARV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10f54ff-19a6-4e44-bea3-0928fb58d098_1200x742.png 424w, https://substackcdn.com/image/fetch/$s_!GARV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10f54ff-19a6-4e44-bea3-0928fb58d098_1200x742.png 848w, https://substackcdn.com/image/fetch/$s_!GARV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10f54ff-19a6-4e44-bea3-0928fb58d098_1200x742.png 1272w, https://substackcdn.com/image/fetch/$s_!GARV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10f54ff-19a6-4e44-bea3-0928fb58d098_1200x742.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p> Some things to note:</p><ul><li><p>Ideation takes longer with just a human, as the feedback loop is quite large. A lot of people sit on ideas for a long time before raising it with developers who could actually implement it. Once it&#8217;s on the backlog, it might take a long time before it&#8217;s picked up.</p></li><li><p>Prototyping takes longer for the human: they need to design the UX and implement the code. It inherently takes longer because AI is able to make an attempt at UX and code without needing to consider design systems or existing code.</p></li><li><p>Testing takes a considerable chunk of time with AI. The human in comparison will test things along the way, as they develop. AI will invent numbers, APIs, and data and run with it.</p></li><li><p>The time to move an AI app to production is longer vs a human, as the human has likely considered things like existing infrastructure, scaling and security practices, and tested along the way as they developed it.</p></li></ul><p>It&#8217;s interesting to see AI used for providing enriched journalistic content. I wouldn&#8217;t trust it yet, which gives me my next goal: figure out how to implement some practices that will reduce the amount of time spent testing and turning the code into production-ready code.  Subscribe if you want to follow that journey!</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/reviewing-a-journalistic-vibe-coded?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/reviewing-a-journalistic-vibe-coded?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2><strong>Appendix: User Input Summary</strong></h2><p><em>These are my questions / given input to Claude</em>.</p><h3><strong>Initial Request</strong></h3><p>Let's make a frontend-only website that helps people figure out which discount they should use using Oslo's Ruter public transport.</p><p>You should allow users to enter how many trips they expect to make per week, then show them the discount they might get.</p><p>The details on Reis are here: <strong><a href="https://ruter.no/om-vare-billetter/reis-enkeltbilletter-med-rabatt">https://ruter.no/om-vare-billetter/reis-enkeltbilletter-med-rabatt</a></strong></p><h3><strong>Feature Requests</strong></h3><h3><strong>Period Ticket Comparison</strong></h3><p>Okay, great. Now add a way to compare against the period tickets. The period ticket information can be found here: <strong><a href="https://ruter.no/om-vare-billetter/periodebillett">https://ruter.no/om-vare-billetter/periodebillett</a></strong></p><h3><strong>Zone Selection</strong></h3><p>Allow the user to put in their Ruter Oslo zones. Use the information found on the websites I gave you to add the correct zone information</p><h3><strong>Current Discount Level</strong></h3><p>Allow the user to specify their current Reis discount, so that the calculation can take that into account</p><h3><strong>Time Period Options</strong></h3><p>Allow the user to choose time periods of:</p><ul><li><p>24 hours</p></li><li><p>7 days</p></li><li><p>30 days</p></li><li><p>365 days</p></li></ul><p>Use the information from the Ruter site I already provided you.</p><h3><strong>Layout Changes</strong></h3><h3><strong>Section Reordering</strong></h3><p>Can you move the Discount Breakdown section to the bottom of the page?</p><h3><strong>Break-Even Analysis</strong></h3><p>Can you also add a section that explains at which point (i.e how many trips) it becomes cheaper to use Reis vs period tickets?</p><h3><strong>Documentation Request</strong></h3><p>Can you summarize all the questions and input I've give you, and put it into a file called "<strong>chat.md</strong>". Only put in my inputs.</p>]]></content:encoded></item><item><title><![CDATA[Schibsted's Open Source office ]]></title><description><![CDATA[Open Source is an important yet overlooked part of a company&#8217;s stack, and our office is dedicated to supporting or encouraging open source. We are a news media company, not a big tech company. So why and how do we contribute to open source?]]></description><link>https://thetechenabler.substack.com/p/schibsteds-open-source-office</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/schibsteds-open-source-office</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Wed, 23 Jul 2025 05:37:16 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!oP35!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e321288-a344-42db-8173-0928b49e0c48_2048x634.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I recently got asked about Schibsted&#8217;s Open Source office, why we have it, and how it works. Open Source is an important yet overlooked part of a company&#8217;s technology stack, and our office is dedicated to supporting or encouraging open source. We are a news media company, not a big tech company. So why and how do we contribute to open source?</p><h3>What&#8217;s an open source office?</h3><p>Small companies can have open source as a normal thing they do. Bigger companies need some way to coordinate their efforts. They might be publishing their own packages, contributing to others with manpower, or contributing with finances. An open source office allows a big company to enact a shared strategy regarding open source across the entire company.</p><h3>Why is open source beneficial for big companies? </h3><p>There&#8217;s a multitude of reasons for commercial companies to be active in open source, but the main motivators for us are:</p><ol><li><p>Increased brand awareness within the developer communities. i.e better hiring potential. Norway and Sweden have relatively small, tight knit developer communities. Companies that actively promote their open source contributions tend to be more attractive than those that don&#8217;t. </p></li><li><p>Developers want to be free to contribute to open source in their personal time. A huge portion of developers spend their personal time coding, so a culture that encourages or supports their ability to do that is beneficial to the company. Happier employees, happier company.</p></li><li><p>Many things that we developed didn&#8217;t benefit from being closed source. I think it&#8217;s debatable whether or not open source projects are of higher quality, but a well-made open source project often contains several factors that have higher quality. Good documentation, good tests, issue management. Since a lot of our code didn&#8217;t provide us a competitive advantage, why not open source it? We&#8217;re a news media company, not a big tech company.</p></li><li><p>We run into bugs with browsers quite often<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>. When that happens, our interactions in the open source community can help find fixes for them. We rarely create the fixes, since we&#8217;re a news media company, not a big tech company with C++ browser engine experts. But we can provide excellent write-ups of problems, and help debug things.</p></li><li><p>We wouldn&#8217;t exist if open source didn&#8217;t exist. Revenue for news media companies is a constant struggle. <a href="https://www.library.hbs.edu/working-knowledge/open-source-software-the-nine-trillion-resource-companies-take-for-granted">HBR published a paper, with a quote from their findings</a>: &#8220;<em>Firms would need to spend 3.5 times more on software than they currently do if OSS did not exist</em>&#8221;. Quite frankly, news media companies cannot afford to spend 3.5 times more on software. We are a news media company, not a big tech company. While it&#8217;s not our obligation to contribute to open source, if every company took the Apple route of limiting employee open source contributions, then open source simply wouldn&#8217;t exist.  </p></li></ol><p>I repeated a phrase a few times there: <strong>We are a news media company, not a big tech company</strong>. Our focus isn&#8217;t designing world famous data structures, pouring research into low-level algorithms. Our focus is delivering news to people - when they want it, what they want to read, and how they want it. Everything we do in tech is to enable that. Traditionally, a lot of the developers in the news industry approached things with the typical hacker mindset: get things done quickly, at scale. There&#8217;s a big overlap in the &#8220;hacker mindset&#8221; community and the open source community. </p><h3>Why would employees want to contribute to open source?</h3><p>There&#8217;s many motivations from employees, but I&#8217;ll sum them up as: a) career growth or b) philosophy. I don&#8217;t think that needs too much clarification, but to expand a little:</p><ol><li><p>Share code with others - or a future self. Make it easier to show others what you did, or come back to what you&#8217;ve done.</p></li><li><p>Raise your public profile - so others know who you are. Get involved in communities that could lead to skill development, social network growth, or career opportunities.</p></li><li><p>Provide a public record of your coding - simplify interviews. If you&#8217;ve got a lot of high quality open source repos, you can often skip interview steps.</p></li><li><p>Engage in bigger technical projects.</p></li><li><p>Develop new skills and specialisms. Often your day job can be radically different from your actual nerdy interest outside of work. In my case, outside of work, I love designing programming languages. I can&#8217;t really do that at work.</p></li></ol><h3>What does the open source office do?</h3><p>The open source office originally was composed of 3 of us: 2 developers, 1 tech management. Together we&#8217;d work to build a community around open source, while also establishing and clarifying procedures. </p><p>We host monthly talks based on different aspects of open source. There has been a mixture of internal speakers, sharing their own experiences, and external speakers. Some of the speakers we had in: <a href="https://varnish-cache.org/index.html">Varnish</a>, <a href="https://www.getunleash.io/">Unleash</a>, <a href="https://github.com/schibsted/WAAS">Whisper as a Service</a>, Arch Linux and NixOS contributors, Derw. When something big happened, like xz&#8217;s backdoor, we held a session on it.</p><p>One of the concrete problems that developers encounter in their daily workflow is usage of external libraries. By default, most developers pull in any library they find, without considering the license. In my experience, young, small companies especially tend to disregard licenses. As companies become bigger or more mature, the legal risk from incorrectly using open source projects becomes a risk that the legal department wouldn&#8217;t be okay with<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>. So to address that, one of our core resources is a policy explaining which licenses were legally okay for the company to use. We&#8217;ve built some tools to map out licenses we use, and created license-specific advice. </p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_5T2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F835dd34b-42c3-45c0-9d01-f63ffd9134ad_658x189.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_5T2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F835dd34b-42c3-45c0-9d01-f63ffd9134ad_658x189.png 424w, https://substackcdn.com/image/fetch/$s_!_5T2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F835dd34b-42c3-45c0-9d01-f63ffd9134ad_658x189.png 848w, https://substackcdn.com/image/fetch/$s_!_5T2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F835dd34b-42c3-45c0-9d01-f63ffd9134ad_658x189.png 1272w, https://substackcdn.com/image/fetch/$s_!_5T2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F835dd34b-42c3-45c0-9d01-f63ffd9134ad_658x189.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_5T2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F835dd34b-42c3-45c0-9d01-f63ffd9134ad_658x189.png" width="658" height="189" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/835dd34b-42c3-45c0-9d01-f63ffd9134ad_658x189.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:189,&quot;width&quot;:658,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!_5T2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F835dd34b-42c3-45c0-9d01-f63ffd9134ad_658x189.png 424w, https://substackcdn.com/image/fetch/$s_!_5T2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F835dd34b-42c3-45c0-9d01-f63ffd9134ad_658x189.png 848w, https://substackcdn.com/image/fetch/$s_!_5T2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F835dd34b-42c3-45c0-9d01-f63ffd9134ad_658x189.png 1272w, https://substackcdn.com/image/fetch/$s_!_5T2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F835dd34b-42c3-45c0-9d01-f63ffd9134ad_658x189.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Some internal example of license mapping</figcaption></figure></div><p>Tools like <a href="https://www.wiz.io/academy/software-bill-of-material-sbom">SBOMs</a> are great for this - so you know what code you&#8217;re actually running in production.</p><p>The other main concern developers have is &#8220;how do I release open source projects&#8221;? I&#8217;ve written up some tips with a very practical real-world example.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;5eea2cf2-54c3-4c7e-9472-3298d5b18d58&quot;,&quot;caption&quot;:&quot;In Schibsted, one of the areas I help with is the open source office. The office exists to help encourage open source internally, both through contributions upstream, or open sourcing things we find useful.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Open sourcing work experiments and libraries &quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:68109252,&quot;name&quot;:&quot;Noah Hall&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8ca672b-8408-4f12-aafd-37e9a28d3506_1047x1047.jpeg&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2024-03-25T06:34:37.583Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ec10577-d183-4733-8363-0773ba130ca7_841x745.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://thetechenabler.substack.com/p/open-sourcing-work-experiments-and&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:142898781,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;The Tech Enabler&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!BQzA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8ca672b-8408-4f12-aafd-37e9a28d3506_1047x1047.jpeg&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>Without going into too much detail, at a high level the process looks something like this:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!oP35!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e321288-a344-42db-8173-0928b49e0c48_2048x634.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!oP35!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e321288-a344-42db-8173-0928b49e0c48_2048x634.png 424w, https://substackcdn.com/image/fetch/$s_!oP35!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e321288-a344-42db-8173-0928b49e0c48_2048x634.png 848w, https://substackcdn.com/image/fetch/$s_!oP35!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e321288-a344-42db-8173-0928b49e0c48_2048x634.png 1272w, https://substackcdn.com/image/fetch/$s_!oP35!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e321288-a344-42db-8173-0928b49e0c48_2048x634.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!oP35!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e321288-a344-42db-8173-0928b49e0c48_2048x634.png" width="611" height="189.1474609375" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7e321288-a344-42db-8173-0928b49e0c48_2048x634.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:634,&quot;width&quot;:2048,&quot;resizeWidth&quot;:611,&quot;bytes&quot;:143664,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!oP35!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e321288-a344-42db-8173-0928b49e0c48_2048x634.png 424w, https://substackcdn.com/image/fetch/$s_!oP35!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e321288-a344-42db-8173-0928b49e0c48_2048x634.png 848w, https://substackcdn.com/image/fetch/$s_!oP35!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e321288-a344-42db-8173-0928b49e0c48_2048x634.png 1272w, https://substackcdn.com/image/fetch/$s_!oP35!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e321288-a344-42db-8173-0928b49e0c48_2048x634.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Open source repos don&#8217;t need to be on-going living projects to be useful. In fact, several of our successful projects are those who were released as finished projects. Very little work has gone into them once we released them - but we <strong>did </strong>release them, giving them to the community. Our ideal combination of released open source projects would include &#8220;finished&#8221; projects, on-going projects, and short-lived experiments or workshop material. Unless a repo is of particularly low quality, it&#8217;s not harmful to have old or archived repos.</p><h3>Inspirational companies leading open source in Norway</h3><p>Within Norway, some companies are absolutely fantastic at open source. The IT organisation for Norwegian labour &amp; welfare, <a href="https://github.com/navikt">Nav IT</a>, in particular is fantastic. A huge amount of things they develop are open source, and they&#8217;re truly impressive. They also <a href="https://nais.io/">released the platform they built internally for themselves, aimed at other public sector organisations.</a> While Schibsted is quite different from Nav<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a>, their open source contributions are inspiring. I frequently bring them up as something to replicate and celebrate. </p><p>Much like Nav&#8217;s release of their Nais platform, Schibsted had a hand in the early days of both Varnish and Unleash. These products were born out of a need that we had, becoming big enough to support a company of dedicated employees to those products. Fully building and funding these tools within Schibsted itself would&#8217;ve been costly, and they probably would&#8217;ve died off after some time - again, we are a news media company, not a big tech company. Varnish is now used by a huge portion of the web - it deserved to scale beyond Schibsted&#8217;s uses.</p><h3>Definitions of success</h3><p>Success can mean many things, and I don&#8217;t think we had any particular OKRs to keep track of our open source contributions. While we have gathered a number of metrics in the past, the majority of time spent doing &#8220;open source office&#8221; things are to build a community. Many of our developers have this interest, so showing that the company is supportive of open source is great for motivation. The talks we&#8217;ve held have had a good audience, and the number of repos we&#8217;ve released always increases after we talk about our support of open source. We aim for T-shaped developers where possible, and open source tends to provide the chance for specialists to gain knowledge in other areas.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eEN-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5da4b73b-b0d4-4d68-974c-09da23b73685_727x395.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eEN-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5da4b73b-b0d4-4d68-974c-09da23b73685_727x395.png 424w, https://substackcdn.com/image/fetch/$s_!eEN-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5da4b73b-b0d4-4d68-974c-09da23b73685_727x395.png 848w, https://substackcdn.com/image/fetch/$s_!eEN-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5da4b73b-b0d4-4d68-974c-09da23b73685_727x395.png 1272w, https://substackcdn.com/image/fetch/$s_!eEN-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5da4b73b-b0d4-4d68-974c-09da23b73685_727x395.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eEN-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5da4b73b-b0d4-4d68-974c-09da23b73685_727x395.png" width="428" height="232.54470426409904" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5da4b73b-b0d4-4d68-974c-09da23b73685_727x395.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:395,&quot;width&quot;:727,&quot;resizeWidth&quot;:428,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!eEN-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5da4b73b-b0d4-4d68-974c-09da23b73685_727x395.png 424w, https://substackcdn.com/image/fetch/$s_!eEN-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5da4b73b-b0d4-4d68-974c-09da23b73685_727x395.png 848w, https://substackcdn.com/image/fetch/$s_!eEN-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5da4b73b-b0d4-4d68-974c-09da23b73685_727x395.png 1272w, https://substackcdn.com/image/fetch/$s_!eEN-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5da4b73b-b0d4-4d68-974c-09da23b73685_727x395.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Source: https://www.highspeedtraining.co.uk/hub/t-shaped-employee/</figcaption></figure></div><p>Some specific metrics that might be useful for strategy:</p><ol><li><p>Number of public repos (active, archived)</p></li><li><p>Number of dead repos (i.e those who aren&#8217;t active, and provide little value)</p></li><li><p>Open Source talks given internally</p></li><li><p>Number of open source libraries used (mapped by which license they use)</p></li><li><p>Time the company has spent on open source (also: money, if you can afford it)</p></li></ol><p>While none of these metrics are perfect for representing the organic open source community within a company, they can give some insight. I consider the open source office to be successful if others have looked up our open source projects, if developers are able to learn or share their niche knowledge, and if there&#8217;s a mindset of &#8220;open source by default&#8221;. Open source by default can be controversial, but the majority of things we build in isolation aren&#8217;t what gives us our competitive advantage. Again, we are a news media company - not a big tech company. Our competitive advantage comes from our approach to journalism, combined with our journalists.</p><h3>Closing thoughts</h3><p>To me, the open source office is the combination of mandate, guild/culture building, and strategy. It has the mandate to clarify key parts of development: what licenses we use, how we build and release products. It supports the culture of open source, forming a guild. And it has the capacity to advise on strategy topics specifically related to open source. While each of these could happen in isolation, I think it&#8217;s likely that a strange bystander affect would happen: nobody would do open source since they expect others to, or because they don&#8217;t know that others are doing it, or because they don&#8217;t know how to do it. I don&#8217;t think there needs to be a open source office in every company, but I&#8217;ve seen success from our initiatives and culture since we started ours.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/schibsteds-open-source-office?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/schibsteds-open-source-office?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p> </p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>You&#8217;d think that if Safari was going to be so awkward and impossible for non-iOS/Mac OS developers to debug, they&#8217;d at least take the courtesy to implement things that match specs from the cross-platform browsers (Firefox, Chrome). As a side-note: while Apple have some big open source projects they contribute to (CUPS, Swift, etc), they also have a culture that <a href="https://news.ycombinator.com/item?id=29490581">restricts open source contributions</a>, even in the developer&#8217;s spare time. I have friends first-hand this has applied to. Clearly Apple has an entirely different position on open source.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>Unless you&#8217;re <a href="https://www.theguardian.com/technology/2025/jun/26/meta-wins-ai-copyright-lawsuit-as-us-judge-rules-against-authors">Meta</a>, <a href="https://www.bbc.com/news/articles/c77vr00enzyo">Anthropic</a>, <a href="https://www.nytimes.com/2023/12/27/business/media/new-york-times-open-ai-microsoft-lawsuit.html">OpenAI</a>, or some other gen AI creator, in which case copyright doesn&#8217;t matter to you, I guess?</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p>There are several ex-Schibsted people in Nav, but I think it&#8217;s just a coincidence - the Norwegian tech industry is small.</p></div></div>]]></content:encoded></item><item><title><![CDATA[Running a vibe-code platform (Coder) on your own infrastructure]]></title><description><![CDATA[Non-devs are vibe-coding programs, without any knowledge on how to read or write code. There&#8217;s no fighting it: the growing number of AI tools make it inevitable. Instead, it&#8217;s easier to safely give people inside your company a way to vibe-code.]]></description><link>https://thetechenabler.substack.com/p/running-a-vibe-code-platform-coder</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/running-a-vibe-code-platform-coder</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Thu, 17 Jul 2025 14:16:34 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!G26O!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29cd3581-c204-4602-9512-abc29dbcb373_1919x1206.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Vibe-coding is very trendy, and not just with tech people. Regular people are using AI to create and run programs, without any knowledge on how to read or write code. There&#8217;s no fighting it: the growing number of AI tools make it inevitable. So instead, it&#8217;s easier to give people inside your company a way to do that that meets good security guidelines. Over the last couple of weeks, I&#8217;ve been setting up Coder.com to run on our infra to meet our guidelines. It&#8217;s impressive the creativity that journalist can have when given the right tools, so we just want to make sure they do it in the right way.</p><h3>What is Coder.com?</h3><p><a href="https://coder.com/">Coder.com</a> is a hosted environment for managing hosted dev environments with editors, terminal access, and AI agent tooling.  </p><p>Here&#8217;s a screenshot of one of the test apps I &#8220;vibe-coded&#8221; through it:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!G26O!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29cd3581-c204-4602-9512-abc29dbcb373_1919x1206.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!G26O!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29cd3581-c204-4602-9512-abc29dbcb373_1919x1206.png 424w, https://substackcdn.com/image/fetch/$s_!G26O!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29cd3581-c204-4602-9512-abc29dbcb373_1919x1206.png 848w, https://substackcdn.com/image/fetch/$s_!G26O!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29cd3581-c204-4602-9512-abc29dbcb373_1919x1206.png 1272w, https://substackcdn.com/image/fetch/$s_!G26O!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29cd3581-c204-4602-9512-abc29dbcb373_1919x1206.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!G26O!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29cd3581-c204-4602-9512-abc29dbcb373_1919x1206.png" width="481" height="302.2767857142857" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/29cd3581-c204-4602-9512-abc29dbcb373_1919x1206.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:915,&quot;width&quot;:1456,&quot;resizeWidth&quot;:481,&quot;bytes&quot;:281129,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/168554531?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29cd3581-c204-4602-9512-abc29dbcb373_1919x1206.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!G26O!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29cd3581-c204-4602-9512-abc29dbcb373_1919x1206.png 424w, https://substackcdn.com/image/fetch/$s_!G26O!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29cd3581-c204-4602-9512-abc29dbcb373_1919x1206.png 848w, https://substackcdn.com/image/fetch/$s_!G26O!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29cd3581-c204-4602-9512-abc29dbcb373_1919x1206.png 1272w, https://substackcdn.com/image/fetch/$s_!G26O!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29cd3581-c204-4602-9512-abc29dbcb373_1919x1206.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>Why Coder?</h3><p>For me, it comes down to main selling points: it can be hosted in your own infra, and it&#8217;s open source. The combination of cloud-hosted code editors (code-server, Claude Code, Windsurf, Cursor, etc) with optional local editors (VSCode, Vim, Jetbrains, etc) makes it handy for both developers and non-developers. </p><p>I&#8217;m pretty impressed with the platform so far. It&#8217;s not perfect, but nothing is. The rough edges seem to be both docs, and user management (currently part of the Premium features). The docs are getting better every day though - and they&#8217;ve launched a bounty program for their open source issues, which is great.</p><h3>Knowledge needed to manage your Coder.com</h3><ul><li><p>Terraform (used for creation of workspaces + managing Coder.com itself)</p></li><li><p>Docker (used for dev environments)</p></li><li><p>How to use your hosting platform (AWS, GCP, Azure, etc)</p></li><li><p>How to use AI APIs</p></li><li><p>OpenConnect (auth management)</p></li></ul><p>It&#8217;s also beneficial to if you know how to ssh in and do some old school debugging.</p><h3>Starting on AWS</h3><p>We use AWS, so I&#8217;ll focus on that, but the same things apply to any cloud provider. Coder <a href="https://coder.com/docs/install/cloud/ec2#launch-a-coder-instance-from-the-from-aws-marketplace">provides an AMI on the AWS marketplace</a>. The recommended EC2 instance size is t2.xlarge, but I managed to test successfully with t3.large without any issues. Make sure to assign a lot of disk space though: 10gb per user seems to be about the right size to me.</p><h3>Security groups</h3><p>On AWS, Coder&#8217;s <a href="https://coder.com/docs/install/cloud/ec2">docs recommend to use the default Security Group</a>. You will probably want to lock this down. I chose to limit both http(s) and ssh to specific IPs. Since Coder uses DERP and STUN, you&#8217;ll need to allow https and UDP to specific STUN servers. Coder uses Google&#8217;s STUN servers by default, so you can limit to those IPs.</p><h3>Naming limitations</h3><p>Coder uses a combination of app name, agent name, workspace name and username to create the hostname for each workspace. Since there&#8217;s a <a href="https://coder.com/docs/admin/networking/port-forwarding#dashboard">DNS limit on subdomains to 63 characters</a>, make sure your username + workspace name are short. I&#8217;d suggest using ID numbers for users, since it&#8217;s separate from their email or display name. That way workspaces can still have meaningful names.</p><h3>Templates</h3><p>The easiest templates to work with are those based on the <a href="https://registry.coder.com/templates/coder/docker">Docker template</a>. The <a href="https://github.com/coder/coder/tree/main/examples/templates/aws-linux">aws-linux template needs additional permissions</a>, including IAM roles that allow for ec2 instance management/creation. For that reason, using the Docker template is easier. I suggest managing templates on the ec2 instance rather than by the web UI, so that way it&#8217;s easier to use your normal workflows/deployment systems (Terraform, Docker, git, etc).</p><h3>Claude Code with Bedrock</h3><p>If you&#8217;re planning to run everything under your enterprise agreements, you might want to use Bedrock. The <a href="https://github.com/coder/registry/tree/main/registry/coder-labs/templates/tasks-docker">tasks-docker</a> template has everything you need to setup a Claude Code instance running with a <a href="https://github.com/coder-contrib/realworld-django-rest-framework-angular">RealWorld Django app</a>. However, if you want to use Bedrock or Vertex to run Claude, you might run into difficulties as the template expects an API key. Follow the <a href="https://docs.anthropic.com/en/docs/claude-code/settings#environment-variables">Claude Code settings guide</a> to figure out which env variables you need, and remove the Claude API key env var. </p><p>In my case, I needed:</p><ul><li><p>CLAUDE_CODE_USE_BEDROCK</p></li><li><p>AWS_ACCESS_KEY_ID</p></li><li><p>AWS_SECRET_ACCESS_KEY</p></li><li><p>AWS_REGION</p></li><li><p>ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION</p></li><li><p>ANTHROPIC_MODEL</p></li><li><p>ANTHROPIC_SMALL_FAST_MODEL</p></li></ul><p>Make sure that you&#8217;re able to use Bedrock with the <a href="https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html">cross-region inference profiles</a> within your legal area (e.g EU), as they have the best performance and the lowest cost. Other models don&#8217;t have prompt caching, so end up costing considerably more when used with Claude Code. You can use Bedrock&#8217;s guardrails to enforce security best practices too.</p><p>Once you&#8217;ve tested the demo, I suggest making your own template that starts from a very basic repo. Make sure to follow <a href="https://www.anthropic.com/engineering/claude-code-best-practices">Claude Code&#8217;s best practices</a>.</p><h3>Final thoughts</h3><p>It was pretty easy to set up. I got everything working as a PoC within a day. Now we&#8217;ll evaluate how our non-technical users find it, and after that see if we can scale it up, or try something else. I&#8217;ll probably share a blog post after that, too.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/running-a-vibe-code-platform-coder?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/running-a-vibe-code-platform-coder?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p> </p>]]></content:encoded></item><item><title><![CDATA[Programming affordance: when a language's patterns make it natural to make mistakes]]></title><description><![CDATA[Many of my philosophies in work life, my volunteer life, and my personal life stem from experiences. As a developer, many of those come from being burnt by rough edges or mistakes, just as health & safety principles come from accidents.]]></description><link>https://thetechenabler.substack.com/p/programming-affordance-when-a-languages</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/programming-affordance-when-a-languages</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Thu, 10 Jul 2025 08:39:26 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!cUlr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40651dce-48c9-4c56-9088-a35f5dc9aa21_682x500.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Many of my philosophies in work life<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>, my volunteer life<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>, and my personal life stem from experiences. As a developer, many of those come from being burnt by rough edges or mistakes. Just as health &amp; safety principles come from accidents, my development practices come from bugs, errors, and mistakes. </p><p>With that in mind, here&#8217;s a war-story from my days running an R&amp;D startup  when we lost all the data we thought we gathered from a psychology study.</p><div><hr></div><p>I founded an R&amp;D startup that worked closely with psychology researchers. We would build tools for gathering data from psychology exercises, which the researchers would use in their studies or assessments.</p><p>One of these tests was the <strong><a href="https://en.wikipedia.org/wiki/Stroop_effect">Stroop test</a></strong> - users would get shown four words in different colours, with one of those colours shown in the middle of the 4 words. The user would have to respond as quickly as possible to pick the right word, through pressing the up/down/left/right keys on their keyboard. The user would be asked to do this with some test words (usually colours, office supplies, words without significant meaning to the user). Once they had an average response time within an acceptable range (in milliseconds), we would introduce some words that we wanted to measure the user's reaction on. For example, if a user was particularly addicted to tea, then their reaction time would be different when "tea" is one of the words they get to choose from than a control wordset without any mention of tea. These tests require complete concentration for a significant period of time.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cUlr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40651dce-48c9-4c56-9088-a35f5dc9aa21_682x500.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cUlr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40651dce-48c9-4c56-9088-a35f5dc9aa21_682x500.png 424w, https://substackcdn.com/image/fetch/$s_!cUlr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40651dce-48c9-4c56-9088-a35f5dc9aa21_682x500.png 848w, https://substackcdn.com/image/fetch/$s_!cUlr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40651dce-48c9-4c56-9088-a35f5dc9aa21_682x500.png 1272w, https://substackcdn.com/image/fetch/$s_!cUlr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40651dce-48c9-4c56-9088-a35f5dc9aa21_682x500.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cUlr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40651dce-48c9-4c56-9088-a35f5dc9aa21_682x500.png" width="300" height="219.94134897360703" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/40651dce-48c9-4c56-9088-a35f5dc9aa21_682x500.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:500,&quot;width&quot;:682,&quot;resizeWidth&quot;:300,&quot;bytes&quot;:25338,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/167839745?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40651dce-48c9-4c56-9088-a35f5dc9aa21_682x500.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!cUlr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40651dce-48c9-4c56-9088-a35f5dc9aa21_682x500.png 424w, https://substackcdn.com/image/fetch/$s_!cUlr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40651dce-48c9-4c56-9088-a35f5dc9aa21_682x500.png 848w, https://substackcdn.com/image/fetch/$s_!cUlr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40651dce-48c9-4c56-9088-a35f5dc9aa21_682x500.png 1272w, https://substackcdn.com/image/fetch/$s_!cUlr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40651dce-48c9-4c56-9088-a35f5dc9aa21_682x500.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">Here, the participant is expected to press the &#8594;arrow, to choose &#8220;Chair&#8221;</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mxfe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656038ae-b70f-459e-98df-9b438eaca7b1_746x487.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mxfe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656038ae-b70f-459e-98df-9b438eaca7b1_746x487.png 424w, https://substackcdn.com/image/fetch/$s_!mxfe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656038ae-b70f-459e-98df-9b438eaca7b1_746x487.png 848w, https://substackcdn.com/image/fetch/$s_!mxfe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656038ae-b70f-459e-98df-9b438eaca7b1_746x487.png 1272w, https://substackcdn.com/image/fetch/$s_!mxfe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656038ae-b70f-459e-98df-9b438eaca7b1_746x487.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mxfe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656038ae-b70f-459e-98df-9b438eaca7b1_746x487.png" width="337" height="219.99865951742626" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/656038ae-b70f-459e-98df-9b438eaca7b1_746x487.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:487,&quot;width&quot;:746,&quot;resizeWidth&quot;:337,&quot;bytes&quot;:27905,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/167839745?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656038ae-b70f-459e-98df-9b438eaca7b1_746x487.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mxfe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656038ae-b70f-459e-98df-9b438eaca7b1_746x487.png 424w, https://substackcdn.com/image/fetch/$s_!mxfe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656038ae-b70f-459e-98df-9b438eaca7b1_746x487.png 848w, https://substackcdn.com/image/fetch/$s_!mxfe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656038ae-b70f-459e-98df-9b438eaca7b1_746x487.png 1272w, https://substackcdn.com/image/fetch/$s_!mxfe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656038ae-b70f-459e-98df-9b438eaca7b1_746x487.png 1456w" sizes="100vw"></picture><div></div></div></a><figcaption class="image-caption">When an addictive word is added, the participant has a different reaction time to the control case (here expected to choose &#8594; &#8220;Water&#8221;)</figcaption></figure></div><p>We built the Stroop test tooling to work with any group of users that the researchers wished to analyze. Sometimes it'd be those addicted to substances, sometimes it would be to measure the societal factors (e.g fear of terrorism). In the normal workflow, we'd get the users to add their study email address so that the researchers could follow up with their results. We'd also send the participants their own results via email, in case they were curious. The tech was boring: a PHP backend, MySQL database, and a minimal JavaScript frontend. The results would be sent after the user had completed the full test, then stored in the database.</p><p>One of the studies assessed a group of people who worked in a high security workplace. They would not have internet access, and we would need to provide a locked down device that would only be used for the study. No problem, we setup a laptop with a locked-down Linux install, and put the code on there to run locally just as had in development. We disabled WiFi, Bluetooth, and anything else we could. These instructions came on the same morning as the test: so as we drove to the location, we were fixing the code and testing.</p><p>We arrive, set up the test, then the study participants all come and take the test. It all seemed good, each participant managed to complete the test successfully. We left feeling good.</p><p>As we arrived back at the office, we realized that the data was missing. All of the data. We had not saved any of the participant responses, and it wasn't clear why. The code had worked locally on the machine when we tested, but not in the secure location. We did, however, have logs. The logs seemed okay, nothing particularly special. Then we decided to test without internet access. The problem became clear.</p><pre><code><code>function saveResults($userEmail, $results) {
    sendUserTheirResults($userEmail, $results);
    saveResultsToDatabase($userEmail, $results);
}

function saveResultsToDatabase($userEmail, $results) {
    ...
}

function sendUserTheirResults($userEmail, $results) {
    mail($userEmail, 'Results', $results) or die();
}</code></code></pre><p>PHP had a popular pattern: <em><strong>do_something() or die()</strong></em>. If <em><strong>do_something</strong></em> failed, then the program would exit early. We used <em><strong>mail() or die().</strong></em> When the email failed to send since there was no internet access, the script would exit before saving the results to the database. We used <em><strong>or die()</strong></em> incorrectly - we should've handled the error gracefully instead of exiting the entire script. We had not saved any of the data from any of the participants. And worse: to run the study again, we'd have to book more time in their calendar, with approval steps all over again.</p><p>Our first idea was to see if we had logged the user interactions somewhere. The frontend would log the results in the console, but since we had many participants, we would run each session in an incognito window, then close the window. We looked at the backend: we had logs, but the requests were sent as POST, with no logs of the body. The good feeling of "<em>we pulled this off</em>" turned into the bad feeling of "<em>we've messed up</em>".</p><p>There was no choice but to own the error, and run the test again. The second time, we made sure to test on-site before getting any participants in. The only change in the code was to replace <em><strong>or die()</strong></em> with some proper error handling.</p><p>While this bug was a costly mistake, we learned from it. Whenever we would deploy code-last minute, we'd try to test it more rigorously. If we were running a study without internet access, we'd make sure to test in the same environment. We hadn't accounted for the environment change, partially due to the short notice for the locked-down machine, but also just because we didn't test with the exact same restrictions.</p><p>But we also started moving all of our backend code away from PHP. It was too easy to make a simple but costly mistake. Our main languages became JavaScript, Go, and Python.</p><p>Consider the same pattern in Node.js:</p><pre><code><code>function sendUserTheirResults(userEmail, results) {
  if (!mail(userEmail, "Results", results)) {
    // this would be a very weird thing to do
    process.exit();
  }
}</code></code></pre><p>The design of languages, APIs, and frameworks can often lead developers to make mistakes. It applies outside of code, too. When you see a trashcan with a circle hole next to one with a rectangular hole, you know instinctively that the bottles go into the circle hole, while other trash goes into the rectangular one. In psychology and design, this is known as an object's <strong><a href="https://en.wikipedia.org/wiki/Affordance">affordance</a></strong>. To go against an object's affordance feels unnatural. It feels wrong to push on a door that has a handle for pulling.</p><p>The same effect applies to code: you could call <em><strong>process.exit()</strong></em> when an optional part of the program has an error, but why would you? That feels wrong. Whereas extending a line with or die seems like a natural choice in a language where that's already an established pattern.</p><p>A principle I follow out of this experience: <strong>If you don't make it easy to do the right thing and awkward to do the wrong thing, </strong><em><strong>people with good intentions will do the wrong thing</strong></em><strong>.</strong></p><div><hr></div><p>If this chapter was fun to read, feel free to <strong><a href="https://leanpub.com/egolessengineering/">sign up for my book waiting list</a></strong>. This is one of the chapters that will be included in a section dedicated to moments that shape my philosophy. It will be released for free as HTML when I'm done - with ebook/physical editions available for a minimal price. The waiting list is just a handy way for me to let you know &#8220;the book is ready&#8221;, with a pre-release copy. Otherwise, have a great summer!</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://leanpub.com/egolessengineering/&quot;,&quot;text&quot;:&quot;Sign up for my book's waiting list&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://leanpub.com/egolessengineering/"><span>Sign up for my book's waiting list</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/programming-affordance-when-a-languages?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/programming-affordance-when-a-languages?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>Tech Enabler in the CTO Office for Schibsted, a news company</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>I&#8217;m the board leader for Tekna&#8217;s Network for Developers. Tekna&#8217;s a STEM union in Norway. We host normal tech events, political events, and represent union members in union and political discussions.</p></div></div>]]></content:encoded></item><item><title><![CDATA[Announcing: Egoless Engineering, a tech enablement handbook]]></title><description><![CDATA[I spend a lot of my time writing, reading, thinking. Often I write to solve problems: either my own problems, or to help others solve their own problems. Writing is a big part of my role at Schibsted. So, I'm writing a book.]]></description><link>https://thetechenabler.substack.com/p/announcing-egoless-engineering-a</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/announcing-egoless-engineering-a</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Tue, 01 Jul 2025 19:03:11 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!x6DK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62a9223d-d19a-449d-a8cb-bb87ec58bc51_2100x3000.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I spend a lot of my time writing, reading, thinking. Often I write to solve problems: either my own problems, or to help others solve their own problems. Writing is a big part of my role at Schibsted, and it&#8217;s been a big part of my open source work too.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!x6DK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62a9223d-d19a-449d-a8cb-bb87ec58bc51_2100x3000.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!x6DK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62a9223d-d19a-449d-a8cb-bb87ec58bc51_2100x3000.png 424w, https://substackcdn.com/image/fetch/$s_!x6DK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62a9223d-d19a-449d-a8cb-bb87ec58bc51_2100x3000.png 848w, https://substackcdn.com/image/fetch/$s_!x6DK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62a9223d-d19a-449d-a8cb-bb87ec58bc51_2100x3000.png 1272w, https://substackcdn.com/image/fetch/$s_!x6DK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62a9223d-d19a-449d-a8cb-bb87ec58bc51_2100x3000.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!x6DK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62a9223d-d19a-449d-a8cb-bb87ec58bc51_2100x3000.png" width="345" height="492.85714285714283" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/62a9223d-d19a-449d-a8cb-bb87ec58bc51_2100x3000.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:2080,&quot;width&quot;:1456,&quot;resizeWidth&quot;:345,&quot;bytes&quot;:159459,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/167290636?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62a9223d-d19a-449d-a8cb-bb87ec58bc51_2100x3000.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!x6DK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62a9223d-d19a-449d-a8cb-bb87ec58bc51_2100x3000.png 424w, https://substackcdn.com/image/fetch/$s_!x6DK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62a9223d-d19a-449d-a8cb-bb87ec58bc51_2100x3000.png 848w, https://substackcdn.com/image/fetch/$s_!x6DK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62a9223d-d19a-449d-a8cb-bb87ec58bc51_2100x3000.png 1272w, https://substackcdn.com/image/fetch/$s_!x6DK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62a9223d-d19a-449d-a8cb-bb87ec58bc51_2100x3000.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><br>So I've decided to write a book! I already have approx 60% of what I have planned. It's a book I can summarize by these two paragraphs, from a previous blog post:<br><br><em>At the start of my career, my ego was absolutely my worst quality. I had to be right, every time. I had to &#8220;win&#8221; every disagreement. I suspect it was big-fish-small-pond syndrome. Through learning to disagree with my peers and friends in healthy ways, I've mostly ditched that. No longer do I care about being right. I instead care that things are done in a way that improves the organisation, the code, and employee happiness.<br><br>I take joy from things being done well, by people who enjoy what they're doing. If I can lift people up so that they can do both, I have succeeded in my role as &#8220;Tech Enabler". The essence of Egoless Engineering.</em><br><br>Once finished, I will release the HTML version for free, with an ebook/print version for some minimal cost for those who might want it. I don't plan for huge success, I just hope I can help others do some things better.</p><p>If that sounds interesting to you, <a href="https://leanpub.com/egolessengineering/">sign up to be notified when it comes out here</a>.</p><div><hr></div><p>To give you a taste of some chapters so far:</p><ul><li><p>Philosophy</p><ul><li><p>Principles for tech enablement</p></li><li><p>In the background vs in the foreground</p></li></ul></li><li><p>Teambuilding</p><ul><li><p>Creating lasting teams</p></li><li><p>Overcoming difficult situations</p></li><li><p>Arguments vs disagreements</p></li><li><p>Taking an authoritative voice</p></li><li><p>Mentorship</p></li></ul></li><li><p>Frameworks and tools I use</p><ul><li><p>Lean, BMC, RAT, etc</p></li><li><p>Design thinking</p></li><li><p>Cynefin</p></li><li><p>Facilitation</p></li></ul></li><li><p>Hands-on development</p><ul><li><p>How I code</p></li><li><p>Open source</p></li></ul></li><li><p>Warstories</p><ul><li><p>The time a service hit MAX_INT on index key on a write-heavy DB</p></li><li><p>Malware that only worked on 3g</p></li><li><p>Exiting a user-response script if they had an invalid email without saving their responses</p></li><li><p>When a domain was not set to auto-renew</p></li></ul></li></ul><p>I have more planned, but I intend for the final thing to be a mixture of stories, practical advice, and reflections.</p><p>So yeah: <a href="https://leanpub.com/egolessengineering/">sign up to be notified when it comes out here</a>.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/announcing-egoless-engineering-a?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/announcing-egoless-engineering-a?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[Hosting a vibe-coding hackathon]]></title><description><![CDATA[I recently hosted a general &#8220;Data & AI&#8221; hackathon at Schibsted, for all and any employees who wanted to join. It got me thinking about how vibe-coding, and hackathon success.]]></description><link>https://thetechenabler.substack.com/p/hosting-a-vibe-coding-hackathon</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/hosting-a-vibe-coding-hackathon</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Sat, 21 Jun 2025 11:05:27 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!v-ZM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526aebed-0743-491e-a79d-d5df41489a4b_575x1079.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I recently hosted a general &#8220;Data &amp; AI&#8221; hackathon at Schibsted, for all and any employees who wanted to join. It got me thinking about how vibe-coding, and hackathon success. </p><p>Hackathon participants tend to fail in one of three stages: ideation, scope, and interest.</p><p>Interest needs the idea of a hackathon to captivate the participant. While many in tech will know what a hackathon is, those outside of tech won&#8217;t - and therefore will probably not be that interested. Vibe-coding is a great way to make hackathons more accessible. But the framing and naming is still tricky. If you managed to get people of all industries to a hackathon, you&#8217;d be able get them to make some interesting prototype with vibe-coding. The real challenge is getting them there in the first place. I don&#8217;t have a good answer for this, though I try to get a &#8220;champion&#8221; within each unit to encourage people to join. Someone they know, respect, and trust.</p><p>Ideation is where most teams drop out after showing up. If they can&#8217;t come up with an idea they like, they won&#8217;t really want to take part. I picture it as the same dilemma of those who work in an industry they&#8217;re passionate about vs job where they&#8217;re just there to survive. If you are passionate about an industry, you&#8217;ll be highly engaged. If you&#8217;re just there to survive, you won&#8217;t want to do anything other than show up. If someone is unable to come up with an idea they&#8217;re passionate about, they won&#8217;t want to take part. </p><p>Breaking the barrier of ideation usually comes down to making the participant aware of the possibilities. I usually sit down with them, ask them what they do, and what they&#8217;re passionate about. Most of the time, it&#8217;s just a matter of linking what a person has been thinking about to something they could feasibly do in a specific time-frame. A great thing about vibe-coding: it reduces massively the time needed to successfully pull off an idea.</p><p>Scope doesn&#8217;t usually make people drop out, but it can be demoralizing so that they don&#8217;t end up demoing what they did. Participants try to tackle everything possible, setting the scope way too big to accomplish something meaningful in the short time a hackathon typically has. There&#8217;s always unexpected blockers. I spent one entire hackathon upgrading packages from Python 2 to Python 3 - I was meant to be making a multiplayer Spotify DJ. As a facilitator, your goal is to help the participants to narrow the scope and prioritize. Don&#8217;t let people spend time upgrading packages if that&#8217;s not what they had in mind at the start. If there are demos involved, visual elements are more appealing than looking at code or backend things. </p><p>Vibe-coding can be very accessible to people, but the problems of people new to hackathons are amplified by ambition, goals, and both too much of them and too little of them. If you&#8217;re facilitating a hackathon with non-tech people, make sure to help the participants filter through their ideas into something that could work.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/hosting-a-vibe-coding-hackathon?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/hosting-a-vibe-coding-hackathon?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><p>Sidenote: during this hackathon, I only had 1.5 hours for myself. I decided to make an entirely vibe-coded Turing-complete Scratch clone. I&#8217;ve called it <a href="https://lovable.dev/projects/c8b116c7-2892-45bf-9fbf-8ced469c534f">VibeCatLine</a>. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!v-ZM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526aebed-0743-491e-a79d-d5df41489a4b_575x1079.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!v-ZM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526aebed-0743-491e-a79d-d5df41489a4b_575x1079.png 424w, https://substackcdn.com/image/fetch/$s_!v-ZM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526aebed-0743-491e-a79d-d5df41489a4b_575x1079.png 848w, https://substackcdn.com/image/fetch/$s_!v-ZM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526aebed-0743-491e-a79d-d5df41489a4b_575x1079.png 1272w, https://substackcdn.com/image/fetch/$s_!v-ZM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526aebed-0743-491e-a79d-d5df41489a4b_575x1079.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!v-ZM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526aebed-0743-491e-a79d-d5df41489a4b_575x1079.png" width="575" height="1079" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/526aebed-0743-491e-a79d-d5df41489a4b_575x1079.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1079,&quot;width&quot;:575,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:54615,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/166453286?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526aebed-0743-491e-a79d-d5df41489a4b_575x1079.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!v-ZM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526aebed-0743-491e-a79d-d5df41489a4b_575x1079.png 424w, https://substackcdn.com/image/fetch/$s_!v-ZM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526aebed-0743-491e-a79d-d5df41489a4b_575x1079.png 848w, https://substackcdn.com/image/fetch/$s_!v-ZM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526aebed-0743-491e-a79d-d5df41489a4b_575x1079.png 1272w, https://substackcdn.com/image/fetch/$s_!v-ZM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526aebed-0743-491e-a79d-d5df41489a4b_575x1079.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p> </p><p>Here&#8217;s FizzBuzz in it:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4CE1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd19b8da1-5c1a-4b18-97ce-2450ee513401_1139x1129.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4CE1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd19b8da1-5c1a-4b18-97ce-2450ee513401_1139x1129.png 424w, https://substackcdn.com/image/fetch/$s_!4CE1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd19b8da1-5c1a-4b18-97ce-2450ee513401_1139x1129.png 848w, https://substackcdn.com/image/fetch/$s_!4CE1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd19b8da1-5c1a-4b18-97ce-2450ee513401_1139x1129.png 1272w, https://substackcdn.com/image/fetch/$s_!4CE1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd19b8da1-5c1a-4b18-97ce-2450ee513401_1139x1129.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4CE1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd19b8da1-5c1a-4b18-97ce-2450ee513401_1139x1129.png" width="727.9970092773438" height="721.6054639807911" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d19b8da1-5c1a-4b18-97ce-2450ee513401_1139x1129.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:1129,&quot;width&quot;:1139,&quot;resizeWidth&quot;:727.9970092773438,&quot;bytes&quot;:106260,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/166453286?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd19b8da1-5c1a-4b18-97ce-2450ee513401_1139x1129.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4CE1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd19b8da1-5c1a-4b18-97ce-2450ee513401_1139x1129.png 424w, https://substackcdn.com/image/fetch/$s_!4CE1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd19b8da1-5c1a-4b18-97ce-2450ee513401_1139x1129.png 848w, https://substackcdn.com/image/fetch/$s_!4CE1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd19b8da1-5c1a-4b18-97ce-2450ee513401_1139x1129.png 1272w, https://substackcdn.com/image/fetch/$s_!4CE1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd19b8da1-5c1a-4b18-97ce-2450ee513401_1139x1129.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uwXl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F314ae72a-8c51-4f06-9b16-4749afee6b90_1139x1129.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uwXl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F314ae72a-8c51-4f06-9b16-4749afee6b90_1139x1129.png 424w, https://substackcdn.com/image/fetch/$s_!uwXl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F314ae72a-8c51-4f06-9b16-4749afee6b90_1139x1129.png 848w, https://substackcdn.com/image/fetch/$s_!uwXl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F314ae72a-8c51-4f06-9b16-4749afee6b90_1139x1129.png 1272w, https://substackcdn.com/image/fetch/$s_!uwXl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F314ae72a-8c51-4f06-9b16-4749afee6b90_1139x1129.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uwXl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F314ae72a-8c51-4f06-9b16-4749afee6b90_1139x1129.png" width="1139" height="1129" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/314ae72a-8c51-4f06-9b16-4749afee6b90_1139x1129.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1129,&quot;width&quot;:1139,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:75159,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/166453286?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F314ae72a-8c51-4f06-9b16-4749afee6b90_1139x1129.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!uwXl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F314ae72a-8c51-4f06-9b16-4749afee6b90_1139x1129.png 424w, https://substackcdn.com/image/fetch/$s_!uwXl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F314ae72a-8c51-4f06-9b16-4749afee6b90_1139x1129.png 848w, https://substackcdn.com/image/fetch/$s_!uwXl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F314ae72a-8c51-4f06-9b16-4749afee6b90_1139x1129.png 1272w, https://substackcdn.com/image/fetch/$s_!uwXl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F314ae72a-8c51-4f06-9b16-4749afee6b90_1139x1129.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[My guidelines for vibe-coding]]></title><description><![CDATA[If you do not know what you are running, you shouldn't be running it. Vibe coding is great for prototypes. Skip the cost of getting designers or developers to build something you've been thinking about. But vibe-code is not production-ready.]]></description><link>https://thetechenabler.substack.com/p/my-guidelines-for-vibe-coding</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/my-guidelines-for-vibe-coding</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Thu, 29 May 2025 17:42:41 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/dadc6a3e-7ea7-4bf7-8d5d-00411564ff06_1686x1705.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you do not know what you are running, you shouldn't be running it. </p><p>Vibe coding is great for prototypes. Skip the cost of getting designers or developers to build something you've been thinking about. But if you want to run something in production, it should not be vibe-coded. You do not understand what it does. You do not know all the systems it depends upon. You do not know what it does with your API keys, with your data, or with your machines. </p><p>Looking through the codebases generated by vibe-coders, I&#8217;ve found numerous problems: severely out of date dependencies, logging of sensitive information / API keys, unnecessary amounts of code, bizarre API calls. These problems exist in human code too, it&#8217;s natural. But vibe-coding is at a different scale.</p><p>Vibe-coding is the equivalent of running random programs you found on the internet. You don&#8217;t know who created it, you don&#8217;t have any kind of protection from what it does. If it breaks something, if it steals something, it is <strong>your</strong> fault. <strong>You are the human</strong>. AI can&#8217;t take responsibility for anything. But you, as a human, must. </p><p>Imagine you are walking through an airport. You see luggage without an owner. You don&#8217;t know what&#8217;s in it. It&#8217;s probably just clothes. But it might be illegal weapons, drugs, etc. Would you be willing to take it through the airport and the rest of your journey? Would you be willing to take it to your family home? </p><p>I would assume the answer is no. After all, airports remind people not to leave their luggage alone. If you see some luggage, you&#8217;re meant to report it to the nearest security staff. </p><p>You, as a vibe-coder, don&#8217;t know what luggage AI is giving you. You might not even know how to recognise signs of suspicion. You definitely aren't equipped to investigate: the luggage is locked, and you don&#8217;t have the key required to open it. The key is knowledge of software engineering. A key that software engineers have spent years earning. </p><p>My objective advice:</p><ul><li><p>Treat AI generated code as if a complete stranger wrote it. After all, the training material has been written by a stranger. Thousands, maybe millions of them.</p></li><li><p>Have 2 human software engineers review the code.</p></li><li><p>Do not give AI API keys. You don&#8217;t know what servers it will give those API keys to.</p></li><li><p>Limit the number of libraries it uses those that have been vetted and approved.</p></li><li><p>Run AI generated code inside of a container (e.g docker) to reduce the possible attack vectors. Do not run it natively on device you wish to protect.</p></li><li><p>Inform those in your company responsible for security, GDPR / data protection, and legal.</p></li><li><p>Establish company-wide prompt regulations for AI tools.</p></li></ul><p>Compared to AI-assisted code, these guidelines are a little more strict. AI-assisted coding tends to have a human at the wheel. Vibe-coding only has the human as a passenger.</p><p>AI&#8217;s given us a great power. We must use it wisely.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;ef330d00-8405-464b-b06a-144fabbab57f&quot;,&quot;caption&quot;:&quot;Since AI-generated code is finding its way into production codebases, I thought it&#8217;d be good to summarise some guidelines I recommend to avoid pitfalls.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;My guidelines for AI-assisted coding&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:68109252,&quot;name&quot;:&quot;Noah Hall&quot;,&quot;bio&quot;:null,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8ca672b-8408-4f12-aafd-37e9a28d3506_1047x1047.jpeg&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2024-10-28T08:11:51.638Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/18b9c41e-bcec-4845-b0b0-032f4f3d806a_1200x800.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://thetechenabler.substack.com/p/my-guidelines-for-ai-assisted-coding&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:150470971,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;The Tech Enabler&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8ca672b-8408-4f12-aafd-37e9a28d3506_1047x1047.jpeg&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/my-guidelines-for-vibe-coding?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/my-guidelines-for-vibe-coding?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p> </p>]]></content:encoded></item><item><title><![CDATA[Code is just a tool]]></title><description><![CDATA[Lots of words are used to refer to software engineers: coder, programmer, developer. I&#8217;ve come to realize that&#8217;s probably a misleading framing. Software engineers aren&#8217;t employed to write code: they&#8217;re employed to deliver on business goals.]]></description><link>https://thetechenabler.substack.com/p/code-is-just-a-tool</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/code-is-just-a-tool</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Sat, 17 May 2025 21:09:56 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/0610d7c3-3e0a-41cf-8a84-e36abcfd457c_1123x590.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Lots of words are used to refer to software engineers: coder, programmer, developer. I usually prefer programmer, but I&#8217;ve come to realize that&#8217;s probably a misleading framing. Software engineers aren&#8217;t employed to write code: they&#8217;re employed to deliver on business goals. </p><p>If we look at &#8220;coder&#8221; first, the implication is someone who writes code. I&#8217;ve seen profile bios on BlueSky where people describe themselves as &#8220;I write code for a living&#8221;<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>. But that's a bit misleading. Software engineers turn designs and business logic into functioning tools and products. Code is one way to do that. But the end goal is never to have a large codebase: it&#8217;s to have a codebase that accomplishes the business goals<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>. </p><p>There&#8217;s the hidden implication that you are paid in direct correlation with the amount of code you produce. But that&#8217;s almost never the case. You are paid in direct correlation with the features and bug fixes you contribute to. Your ability to deliver features or bug fixes might indeed be through code: but it might also be through infrastructure, through reducing tech debt, through simplifying codebases, or through empowering others to solve those problems.</p><p>What about &#8220;developer&#8221;? Someone who develops things. Develops implies something ongoing, something improving over time. Usually &#8220;the situation is developing&#8221; implies that additional things are happening. But the other side of development is that things become refined, and improved. Sometimes through reducing features, a product can become better at delivering value to users or the business. Through reducing the amount of code, the complexity of a codebase can become easier to work with.</p><p>Finally my personal preference: &#8220;programmer&#8221;. I used to take this to mean someone who creates programs, but I like the idea that it refers to someone who creates, configures, cleans up and manages a program. I do still have the connotation in my head of creation being the main aspect, so I&#8217;m not thrilled at that.</p><p>I&#8217;ll probably stop using all of these, in favour of "software engineer&#8221;. If we take a couple of the definitions for &#8220;engineer&#8221;:</p><blockquote><p><strong>a person who designs, builds, or maintains engines, machines, or structures.</strong></p><p><strong>a person who controls an engine, especially on an aircraft or ship.</strong></p></blockquote><p>So much of our focus in tech is on writing code. It&#8217;s probably what we&#8217;re best at. It&#8217;s our main unique skill that we can offer a company. But that&#8217;s not all we do - and we know that the best code is often no or little code. </p><p>As the entire industry adapts to generative AI and vibe-coding, I suspect the better place to frame our skills is that we are there to manage, control, maintain, design and build software. Notice &#8220;build&#8221; came last in that list - if vibe-coders can build things now, can they really do any of the others? </p><p>In the case of Schibsted Media, where I work, I summed these thoughts up as:</p><blockquote><p><strong>You aren&#8217;t here to make designs, write code, or manage backlogs</strong></p><p><strong>You&#8217;re here to deliver news to users who love our sites</strong></p><p><strong>In a way that makes sustainable revenue</strong></p></blockquote><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/code-is-just-a-tool?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/code-is-just-a-tool?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>This isn&#8217;t to call anyone out - writing code is fun, and so many of us do it in our free time. Of course we want to bond with internet strangers over that. But it&#8217;s not actually how we produce value - it&#8217;s one way, yes, but not the only way.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>Unless you work in a scary company that judges output based on lines of code, in which case I really hope you&#8217;re writing Java. If it&#8217;s number of files, I really hope you&#8217;re using React/Vue/Svelte.</p></div></div>]]></content:encoded></item><item><title><![CDATA[Choose the right structure at the start]]></title><description><![CDATA[A good data structure can simplify code.&#160;Tegan's a toy language I made for a talk, based on the idea of having the right data structure simplifying everything else that's nice for languages.]]></description><link>https://thetechenabler.substack.com/p/choose-the-right-structure-at-the</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/choose-the-right-structure-at-the</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Thu, 01 May 2025 16:02:52 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!g68o!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd831e1b-eefe-42fe-be84-a676e5df9c04_2069x1080.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I gave a <a href="https://slides.com/noahhall-3/so-you-re-making-a-new-programming-language">talk this week</a> on a new programming language I created specifically for that talk. Let me tell you about <a href="https://github.com/eeue56/tegan-lang">Tegan</a>. Tegan means &#8220;toy&#8221; in Welsh, literally a toy language. It's stack-based, so every operation is the manipulation of either the main stack, short lived local stacks, or named stacks. It has no way to define functions, only to use those which are built in. It doesn't support floating point, or booleans, or objects - only single line strings and integers. It doesn&#8217;t have types. By most standards, it&#8217;s not a good language.</p><p>It does however have an LSP. It has syntax highlighting in VSCode. It has a debugger. It has a REPL. It can run interpreted in Node, or in the browser. It can compile to native code. It has a web-based playground. It has an auto-formatter. It has inline errors.</p><p>The idea behind Tegan isn&#8217;t to be a good language. But to show how simple some features can be, if you approach a problem can be from the right direction. Often developers, myself included, try to tackle too many problems all at once. But taking a minute to pause and think about the structure of code before starting is often fruitful later. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!g68o!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd831e1b-eefe-42fe-be84-a676e5df9c04_2069x1080.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!g68o!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd831e1b-eefe-42fe-be84-a676e5df9c04_2069x1080.png 424w, https://substackcdn.com/image/fetch/$s_!g68o!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd831e1b-eefe-42fe-be84-a676e5df9c04_2069x1080.png 848w, https://substackcdn.com/image/fetch/$s_!g68o!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd831e1b-eefe-42fe-be84-a676e5df9c04_2069x1080.png 1272w, https://substackcdn.com/image/fetch/$s_!g68o!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd831e1b-eefe-42fe-be84-a676e5df9c04_2069x1080.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!g68o!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd831e1b-eefe-42fe-be84-a676e5df9c04_2069x1080.png" width="2069" height="1080" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dd831e1b-eefe-42fe-be84-a676e5df9c04_2069x1080.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1080,&quot;width&quot;:2069,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:125255,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/162611317?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9be57853-9317-4727-8446-e70f82360797_2069x1897.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!g68o!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd831e1b-eefe-42fe-be84-a676e5df9c04_2069x1080.png 424w, https://substackcdn.com/image/fetch/$s_!g68o!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd831e1b-eefe-42fe-be84-a676e5df9c04_2069x1080.png 848w, https://substackcdn.com/image/fetch/$s_!g68o!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd831e1b-eefe-42fe-be84-a676e5df9c04_2069x1080.png 1272w, https://substackcdn.com/image/fetch/$s_!g68o!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdd831e1b-eefe-42fe-be84-a676e5df9c04_2069x1080.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>For compilers, getting the AST for both the tokens and the expressions can vastly impact how complex it is to later add errors, multiple targets, or editor support. If you think about line numbers, indexes, or a full representation of the tokens and syntax tree of a program, so many things become easier.</p><p>The same thing applies to most programs. Before I write code, I ask myself: &#8220;what unknowns exist, and what do I already know that could be re-applied?&#8221;. With most coding, your knowledge from different domains can be applied again. Humans (and AI, I guess) tend to make code in similar ways, over and over, with slight changes. When was the last time you encountered an API that worked in a totally unfamiliar, new, and novel way for you? It&#8217;s a pretty infrequent occurrence. The structure you chose to use, based on what past experiences have taught you, can reduce the amount of time it takes to integrate with an API.</p><p>A good data structure can simplify code. Data structures with too many optional fields, unclear nesting, or mismatched impossible states tend to complicated code. Breaking things down into distinct, separate members of a union help clear up code paths and reduce the complexity in introducing <em>safe</em> changes. It&#8217;s one reason I start with types before I start with code, and recommend that for others.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/choose-the-right-structure-at-the?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/choose-the-right-structure-at-the?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h3>Tegan itself</h3><p>Tegan is a mostly a side-note for this article, but I figured I&#8217;d include further reading if people were interested. Tegan is a great example of how the right data structures simplifies everything. Beyond the parsing and runtime logic, the majority of tooling features (LSP, etc) came for free from the data structures used.</p><p>Here&#8217;s some screenshots. You could also <a href="https://www.tekna.no/en/professional-areas/it-and-telecommunications/inside-the-compiler-language-design-and-compilation/">watch the talk</a>, or <a href="https://slides.com/noahhall-3/so-you-re-making-a-new-programming-language">just look at the slides</a> or <a href="https://github.com/eeue56/tegan-lang">the repo</a>. </p><p>Some screenshots of the playground:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!STLW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf05b320-a3ee-4128-b69e-30750df4c7ca_1067x686.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!STLW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf05b320-a3ee-4128-b69e-30750df4c7ca_1067x686.png 424w, https://substackcdn.com/image/fetch/$s_!STLW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf05b320-a3ee-4128-b69e-30750df4c7ca_1067x686.png 848w, https://substackcdn.com/image/fetch/$s_!STLW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf05b320-a3ee-4128-b69e-30750df4c7ca_1067x686.png 1272w, https://substackcdn.com/image/fetch/$s_!STLW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf05b320-a3ee-4128-b69e-30750df4c7ca_1067x686.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!STLW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf05b320-a3ee-4128-b69e-30750df4c7ca_1067x686.png" width="426" height="273.8856607310216" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/af05b320-a3ee-4128-b69e-30750df4c7ca_1067x686.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:686,&quot;width&quot;:1067,&quot;resizeWidth&quot;:426,&quot;bytes&quot;:100489,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/162611317?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf05b320-a3ee-4128-b69e-30750df4c7ca_1067x686.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!STLW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf05b320-a3ee-4128-b69e-30750df4c7ca_1067x686.png 424w, https://substackcdn.com/image/fetch/$s_!STLW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf05b320-a3ee-4128-b69e-30750df4c7ca_1067x686.png 848w, https://substackcdn.com/image/fetch/$s_!STLW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf05b320-a3ee-4128-b69e-30750df4c7ca_1067x686.png 1272w, https://substackcdn.com/image/fetch/$s_!STLW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf05b320-a3ee-4128-b69e-30750df4c7ca_1067x686.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The playground supports error highlighting + messages, simple if you store token start and end indexes</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!THzC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2781312a-cf0c-4fdc-9001-1c33fe1a9f1c_1860x1180.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!THzC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2781312a-cf0c-4fdc-9001-1c33fe1a9f1c_1860x1180.png 424w, https://substackcdn.com/image/fetch/$s_!THzC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2781312a-cf0c-4fdc-9001-1c33fe1a9f1c_1860x1180.png 848w, https://substackcdn.com/image/fetch/$s_!THzC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2781312a-cf0c-4fdc-9001-1c33fe1a9f1c_1860x1180.png 1272w, https://substackcdn.com/image/fetch/$s_!THzC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2781312a-cf0c-4fdc-9001-1c33fe1a9f1c_1860x1180.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!THzC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2781312a-cf0c-4fdc-9001-1c33fe1a9f1c_1860x1180.png" width="568" height="360.46153846153845" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2781312a-cf0c-4fdc-9001-1c33fe1a9f1c_1860x1180.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:924,&quot;width&quot;:1456,&quot;resizeWidth&quot;:568,&quot;bytes&quot;:118832,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/162611317?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2781312a-cf0c-4fdc-9001-1c33fe1a9f1c_1860x1180.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!THzC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2781312a-cf0c-4fdc-9001-1c33fe1a9f1c_1860x1180.png 424w, https://substackcdn.com/image/fetch/$s_!THzC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2781312a-cf0c-4fdc-9001-1c33fe1a9f1c_1860x1180.png 848w, https://substackcdn.com/image/fetch/$s_!THzC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2781312a-cf0c-4fdc-9001-1c33fe1a9f1c_1860x1180.png 1272w, https://substackcdn.com/image/fetch/$s_!THzC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2781312a-cf0c-4fdc-9001-1c33fe1a9f1c_1860x1180.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The playground can run the code, with print going to the console, but the stack is shown at the end</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5hX0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab657fad-7959-4c34-bc53-b473cd445777_1074x650.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5hX0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab657fad-7959-4c34-bc53-b473cd445777_1074x650.gif 424w, https://substackcdn.com/image/fetch/$s_!5hX0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab657fad-7959-4c34-bc53-b473cd445777_1074x650.gif 848w, https://substackcdn.com/image/fetch/$s_!5hX0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab657fad-7959-4c34-bc53-b473cd445777_1074x650.gif 1272w, https://substackcdn.com/image/fetch/$s_!5hX0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab657fad-7959-4c34-bc53-b473cd445777_1074x650.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5hX0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab657fad-7959-4c34-bc53-b473cd445777_1074x650.gif" width="460" height="278.39851024208565" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ab657fad-7959-4c34-bc53-b473cd445777_1074x650.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:650,&quot;width&quot;:1074,&quot;resizeWidth&quot;:460,&quot;bytes&quot;:4771029,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/162611317?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab657fad-7959-4c34-bc53-b473cd445777_1074x650.gif&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5hX0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab657fad-7959-4c34-bc53-b473cd445777_1074x650.gif 424w, https://substackcdn.com/image/fetch/$s_!5hX0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab657fad-7959-4c34-bc53-b473cd445777_1074x650.gif 848w, https://substackcdn.com/image/fetch/$s_!5hX0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab657fad-7959-4c34-bc53-b473cd445777_1074x650.gif 1272w, https://substackcdn.com/image/fetch/$s_!5hX0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab657fad-7959-4c34-bc53-b473cd445777_1074x650.gif 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Because the AST + Tegan generators are written in JavaScript, they&#8217;re available in the playground as well as locally</figcaption></figure></div><p>Screenshots of vscode:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mcjv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb806c386-c005-4562-99a8-13ffdcdceada_963x483.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mcjv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb806c386-c005-4562-99a8-13ffdcdceada_963x483.png 424w, https://substackcdn.com/image/fetch/$s_!mcjv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb806c386-c005-4562-99a8-13ffdcdceada_963x483.png 848w, https://substackcdn.com/image/fetch/$s_!mcjv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb806c386-c005-4562-99a8-13ffdcdceada_963x483.png 1272w, https://substackcdn.com/image/fetch/$s_!mcjv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb806c386-c005-4562-99a8-13ffdcdceada_963x483.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mcjv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb806c386-c005-4562-99a8-13ffdcdceada_963x483.png" width="496" height="248.77258566978193" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b806c386-c005-4562-99a8-13ffdcdceada_963x483.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:483,&quot;width&quot;:963,&quot;resizeWidth&quot;:496,&quot;bytes&quot;:82193,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/162611317?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb806c386-c005-4562-99a8-13ffdcdceada_963x483.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mcjv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb806c386-c005-4562-99a8-13ffdcdceada_963x483.png 424w, https://substackcdn.com/image/fetch/$s_!mcjv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb806c386-c005-4562-99a8-13ffdcdceada_963x483.png 848w, https://substackcdn.com/image/fetch/$s_!mcjv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb806c386-c005-4562-99a8-13ffdcdceada_963x483.png 1272w, https://substackcdn.com/image/fetch/$s_!mcjv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb806c386-c005-4562-99a8-13ffdcdceada_963x483.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Syntax highlighting is provided via a VSCode&#8217;s semantic token API, took a very short amount of time to get working based on my own tokenizer vs the old days of writing a regex. </figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eBvs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d9f726-eead-420e-8d77-5bbcad6e9ee0_1475x1199.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eBvs!,w_424,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d9f726-eead-420e-8d77-5bbcad6e9ee0_1475x1199.gif 424w, https://substackcdn.com/image/fetch/$s_!eBvs!,w_848,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d9f726-eead-420e-8d77-5bbcad6e9ee0_1475x1199.gif 848w, https://substackcdn.com/image/fetch/$s_!eBvs!,w_1272,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d9f726-eead-420e-8d77-5bbcad6e9ee0_1475x1199.gif 1272w, https://substackcdn.com/image/fetch/$s_!eBvs!,w_1456,c_limit,f_webp,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d9f726-eead-420e-8d77-5bbcad6e9ee0_1475x1199.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eBvs!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d9f726-eead-420e-8d77-5bbcad6e9ee0_1475x1199.gif" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e9d9f726-eead-420e-8d77-5bbcad6e9ee0_1475x1199.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:20601136,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/162611317?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d9f726-eead-420e-8d77-5bbcad6e9ee0_1475x1199.gif&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!eBvs!,w_424,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d9f726-eead-420e-8d77-5bbcad6e9ee0_1475x1199.gif 424w, https://substackcdn.com/image/fetch/$s_!eBvs!,w_848,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d9f726-eead-420e-8d77-5bbcad6e9ee0_1475x1199.gif 848w, https://substackcdn.com/image/fetch/$s_!eBvs!,w_1272,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d9f726-eead-420e-8d77-5bbcad6e9ee0_1475x1199.gif 1272w, https://substackcdn.com/image/fetch/$s_!eBvs!,w_1456,c_limit,f_auto,q_auto:good,fl_lossy/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d9f726-eead-420e-8d77-5bbcad6e9ee0_1475x1199.gif 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pKg6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9d1904-5eba-499a-a781-9c903f99cbb4_975x1107.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pKg6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9d1904-5eba-499a-a781-9c903f99cbb4_975x1107.png 424w, https://substackcdn.com/image/fetch/$s_!pKg6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9d1904-5eba-499a-a781-9c903f99cbb4_975x1107.png 848w, https://substackcdn.com/image/fetch/$s_!pKg6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9d1904-5eba-499a-a781-9c903f99cbb4_975x1107.png 1272w, https://substackcdn.com/image/fetch/$s_!pKg6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9d1904-5eba-499a-a781-9c903f99cbb4_975x1107.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pKg6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9d1904-5eba-499a-a781-9c903f99cbb4_975x1107.png" width="358" height="406.4676923076923" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ca9d1904-5eba-499a-a781-9c903f99cbb4_975x1107.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1107,&quot;width&quot;:975,&quot;resizeWidth&quot;:358,&quot;bytes&quot;:109435,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/162611317?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9d1904-5eba-499a-a781-9c903f99cbb4_975x1107.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!pKg6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9d1904-5eba-499a-a781-9c903f99cbb4_975x1107.png 424w, https://substackcdn.com/image/fetch/$s_!pKg6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9d1904-5eba-499a-a781-9c903f99cbb4_975x1107.png 848w, https://substackcdn.com/image/fetch/$s_!pKg6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9d1904-5eba-499a-a781-9c903f99cbb4_975x1107.png 1272w, https://substackcdn.com/image/fetch/$s_!pKg6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca9d1904-5eba-499a-a781-9c903f99cbb4_975x1107.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Files can be run via command palette, provided by the extension</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kJ1h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F471fe9c5-c94d-47d6-9b8f-47abb12131e6_975x497.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kJ1h!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F471fe9c5-c94d-47d6-9b8f-47abb12131e6_975x497.png 424w, https://substackcdn.com/image/fetch/$s_!kJ1h!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F471fe9c5-c94d-47d6-9b8f-47abb12131e6_975x497.png 848w, https://substackcdn.com/image/fetch/$s_!kJ1h!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F471fe9c5-c94d-47d6-9b8f-47abb12131e6_975x497.png 1272w, https://substackcdn.com/image/fetch/$s_!kJ1h!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F471fe9c5-c94d-47d6-9b8f-47abb12131e6_975x497.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kJ1h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F471fe9c5-c94d-47d6-9b8f-47abb12131e6_975x497.png" width="457" height="232.95282051282052" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/471fe9c5-c94d-47d6-9b8f-47abb12131e6_975x497.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:497,&quot;width&quot;:975,&quot;resizeWidth&quot;:457,&quot;bytes&quot;:101206,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/162611317?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F471fe9c5-c94d-47d6-9b8f-47abb12131e6_975x497.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!kJ1h!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F471fe9c5-c94d-47d6-9b8f-47abb12131e6_975x497.png 424w, https://substackcdn.com/image/fetch/$s_!kJ1h!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F471fe9c5-c94d-47d6-9b8f-47abb12131e6_975x497.png 848w, https://substackcdn.com/image/fetch/$s_!kJ1h!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F471fe9c5-c94d-47d6-9b8f-47abb12131e6_975x497.png 1272w, https://substackcdn.com/image/fetch/$s_!kJ1h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F471fe9c5-c94d-47d6-9b8f-47abb12131e6_975x497.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Same errors as in the terminal and playground, though everything also has a hover message (in this case, the help text for &#8220;sum&#8221;)</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8E8u!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e34e652-851e-4235-b885-ae51e58a97df_796x873.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8E8u!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e34e652-851e-4235-b885-ae51e58a97df_796x873.png 424w, https://substackcdn.com/image/fetch/$s_!8E8u!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e34e652-851e-4235-b885-ae51e58a97df_796x873.png 848w, https://substackcdn.com/image/fetch/$s_!8E8u!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e34e652-851e-4235-b885-ae51e58a97df_796x873.png 1272w, https://substackcdn.com/image/fetch/$s_!8E8u!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e34e652-851e-4235-b885-ae51e58a97df_796x873.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8E8u!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e34e652-851e-4235-b885-ae51e58a97df_796x873.png" width="319" height="349.85804020100505" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7e34e652-851e-4235-b885-ae51e58a97df_796x873.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:873,&quot;width&quot;:796,&quot;resizeWidth&quot;:319,&quot;bytes&quot;:67096,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/162611317?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e34e652-851e-4235-b885-ae51e58a97df_796x873.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!8E8u!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e34e652-851e-4235-b885-ae51e58a97df_796x873.png 424w, https://substackcdn.com/image/fetch/$s_!8E8u!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e34e652-851e-4235-b885-ae51e58a97df_796x873.png 848w, https://substackcdn.com/image/fetch/$s_!8E8u!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e34e652-851e-4235-b885-ae51e58a97df_796x873.png 1272w, https://substackcdn.com/image/fetch/$s_!8E8u!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e34e652-851e-4235-b885-ae51e58a97df_796x873.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The repl, which takes about 100 lines of code to implement</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mi2J!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F839e02ae-203c-48b0-939d-589846bdae31_355x172.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mi2J!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F839e02ae-203c-48b0-939d-589846bdae31_355x172.png 424w, https://substackcdn.com/image/fetch/$s_!mi2J!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F839e02ae-203c-48b0-939d-589846bdae31_355x172.png 848w, https://substackcdn.com/image/fetch/$s_!mi2J!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F839e02ae-203c-48b0-939d-589846bdae31_355x172.png 1272w, https://substackcdn.com/image/fetch/$s_!mi2J!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F839e02ae-203c-48b0-939d-589846bdae31_355x172.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mi2J!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F839e02ae-203c-48b0-939d-589846bdae31_355x172.png" width="355" height="172" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/839e02ae-203c-48b0-939d-589846bdae31_355x172.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:172,&quot;width&quot;:355,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:16768,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/162611317?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F839e02ae-203c-48b0-939d-589846bdae31_355x172.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mi2J!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F839e02ae-203c-48b0-939d-589846bdae31_355x172.png 424w, https://substackcdn.com/image/fetch/$s_!mi2J!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F839e02ae-203c-48b0-939d-589846bdae31_355x172.png 848w, https://substackcdn.com/image/fetch/$s_!mi2J!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F839e02ae-203c-48b0-939d-589846bdae31_355x172.png 1272w, https://substackcdn.com/image/fetch/$s_!mi2J!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F839e02ae-203c-48b0-939d-589846bdae31_355x172.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">The debugger is triggered via the `debug` function</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qkUW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1e0baf-ef77-4ab6-af0b-ef75e3b73663_899x1017.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qkUW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1e0baf-ef77-4ab6-af0b-ef75e3b73663_899x1017.png 424w, https://substackcdn.com/image/fetch/$s_!qkUW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1e0baf-ef77-4ab6-af0b-ef75e3b73663_899x1017.png 848w, https://substackcdn.com/image/fetch/$s_!qkUW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1e0baf-ef77-4ab6-af0b-ef75e3b73663_899x1017.png 1272w, https://substackcdn.com/image/fetch/$s_!qkUW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1e0baf-ef77-4ab6-af0b-ef75e3b73663_899x1017.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qkUW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1e0baf-ef77-4ab6-af0b-ef75e3b73663_899x1017.png" width="408" height="461.5528364849833" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0c1e0baf-ef77-4ab6-af0b-ef75e3b73663_899x1017.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1017,&quot;width&quot;:899,&quot;resizeWidth&quot;:408,&quot;bytes&quot;:117416,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/162611317?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3f79493-ff29-4ca9-ac9e-97b482efe244_899x1017.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qkUW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1e0baf-ef77-4ab6-af0b-ef75e3b73663_899x1017.png 424w, https://substackcdn.com/image/fetch/$s_!qkUW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1e0baf-ef77-4ab6-af0b-ef75e3b73663_899x1017.png 848w, https://substackcdn.com/image/fetch/$s_!qkUW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1e0baf-ef77-4ab6-af0b-ef75e3b73663_899x1017.png 1272w, https://substackcdn.com/image/fetch/$s_!qkUW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1e0baf-ef77-4ab6-af0b-ef75e3b73663_899x1017.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Then when the debugger is triggered, you can run whatever operations you want, then continue the program - or step through/over.</figcaption></figure></div><p></p>]]></content:encoded></item><item><title><![CDATA[Writing a re-org post-mortem]]></title><description><![CDATA[In 2016, our company began a big shift in how we worked with our technical stacks. In 2023, when the project was shut down, a colleague and I were given the task of documenting what went wrong, and what went right. A post-mortem on steroids.]]></description><link>https://thetechenabler.substack.com/p/writing-a-re-org-post-mortem</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/writing-a-re-org-post-mortem</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Thu, 10 Apr 2025 10:05:47 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/3b5fc32d-534a-4502-a069-1aa5219cae98_1920x1080.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In 2016, our company began a big shift in how we worked with our technical stacks. It didn&#8217;t end work out in the end, but it took a long time (2023) for that to be truly realised. In 2023, when the project was shut down, a colleague and I were given the task of documenting what went wrong, and what went right. This documentation was effectively a post-mortem on steroids - 10 team retros, 60 participants with many individual interviews after. The write up is about 1/3rd the length of the first Harry Potter book. Since the report was written, about 180 of the product &amp; tech organisation have read it, and we&#8217;ve given multiple presentations on top. Others have listened to it in podcast form, thanks to Notebook LLM. This document is probably the most consistently mentioned historical artifact our tech organisation refers to.</p><h3>The objectives</h3><p>To figure out who we needed to talk to, we needed some clear objectives. Objectives that would help us understand <em>why</em> we needed to talk to people. Once you know <em>why</em> you are analyzing something, figuring out <em>who</em> you should talk is a bit easier to think about.</p><p>Our objectives were straightforward: objectively document why this attempt failed, to use these learnings for the future. There was considerable frustration within tech, so an additional objective was to give people a chance to air these frustrations.</p><h3>The process</h3><p>There were some teams that were clear we should talk to: those who worked on the central stack, and stakeholder teams that worked directly with the central stack team. We realised half-way through that it would be beneficial to talk to management, too - to understand both the concept, and how different problems were managed.</p><p>That left us with two types of retros: team retros, and individual interviews.</p><p>For both the retros and interviews, we&#8217;d take both written notes, and an audio transcription. For retros, we also had postit notes from those who took part - grouped into categories we had defined beforehand.</p><p>As the whole centralizing had caused considerable frustration, we felt it was important to avoid directly attributing any quotes to specific people, where possible. When we did directly attribute people, we gave them both the quote and the context beforehand - so they could either approve or reject the quote. </p><p>The goal was not to blame to specific people - it was to understand what happened. Much like blameless post-mortem culture, this report could be thought of as blameless analysis. However, it&#8217;s good to note - there were problems to blame, and we didn&#8217;t hold back on that. But in blameless post-mortems, you blame <em>processes</em> and not <em>people</em>. </p><p>We were sure to highlight as many problems with the process of centralizing as we could. At the same time, we also made sure to highlight any successes. For any future learning, focusing on both things that went particularly well and particularly badly is highlight valuable. Things that went badly can be avoided, or done differently. <strong>But you also want to repeat the things that were done well</strong>.</p><p>Once we ran all the sessions with teams and individuals, we then turned the notes from each session into a summary for that specific individual or team. Other than me and the other author of the report, nobody else would see the transcribed notes we had taken. Very intentionally, we avoided leaking any direct quotes.</p><p>The summaries were provided in the report, but were also used to provide executive summaries, do&#8217;s and don&#8217;t, and specific topic-basic summaries. </p><p>The report is pretty huge - so we intentionally make it possible for people to read a specific section without needing to read the whole document. Google Docs&#8217; sections and headlines makes it easy for people to dive to a specific team, for example. We assumed that most team members would be interested in reading the executive summary + their own team&#8217;s summary.</p><h3>What about bias?</h3><p>Both myself and my co-author were involved in some way. Myself as a user of the platform, and the co-author as someone who was on that team. We naturally had opinions, and biases. But the objective was not &#8220;write up what Noah and Hilde think about CNP&#8221;, it was &#8220;document what went right and wrong with CNP&#8221;. We took part in two of the sessions as participants, where we voiced our opinions, but in every other session and the write up, we tried to reflect the opinions of the org. It can be pretty challenging to avoid that, on a topic you&#8217;re passionate about. However, if we were afraid of bias, we&#8217;d discuss with each other to make sure we&#8217;re grounded.</p><p>In the document, and in presentations, we made sure to explicitly mention bias. The document is mostly free of our personal bias, but in presentations, we would often include things that we felt didn&#8217;t fit in the report, but was important for others to hear. For example, our personal recommendations, or tough-but-fair feedback that management needed to hear.</p><h3>Then what?</h3><p>We feared when writing that nobody would read it. Or that management would ignore it. Instead, the opposite is true. Several people have read it multiple times - including management. Both me, my co-author, and others in management frequently mention or send it to others, and we know they read it.</p><p>A core aspect of why so many people have read it is that for several years, this was a heated topic within teams. People had strong opinions and frustrations, possibly for the majority of the time they were in the company. The report is a healing factor: showing the company not only cares about doing things differently in future, but also giving a voice to employees. </p><p>I&#8217;m personally pretty happy with the outcome. It took a lot of time and energy, and so much rewriting to get each phrase just right. But I&#8217;m proud that the company both gave us the time and resources to write the report, and that the company has received it well.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/writing-a-re-org-post-mortem?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/writing-a-re-org-post-mortem?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/subscribe?"><span>Subscribe now</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[Keeping your head up during tough times at work]]></title><description><![CDATA[My employer, like many tech companies, is going through cost cuts. But I&#8217;m not too worried about my job. I know many colleagues, many of them very well. The tough times they face are tough times I face.This is how I've been keeping my head up.]]></description><link>https://thetechenabler.substack.com/p/keeping-your-head-up-during-tough</link><guid isPermaLink="false">https://thetechenabler.substack.com/p/keeping-your-head-up-during-tough</guid><dc:creator><![CDATA[Noah Hall]]></dc:creator><pubDate>Thu, 20 Mar 2025 21:44:21 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Fs2P!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6259d6-364a-407b-9b6d-0a9d29056d36_1134x628.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>My employer, like many tech companies, is going through layoffs. While it&#8217;s too early to say with certainty, my role is <em>probably</em> fine. Even if it wasn&#8217;t, I&#8217;m not too worried about finding another employer. So, I&#8217;m not going to be writing a &#8220;please hire me&#8221; post. Instead, since a big part of being a &#8220;tech enabler&#8221; is broad across the organisation, I thought it would be interesting to share how I&#8217;ve been keeping my head up during this period. I know many colleagues, many of them very well. The tough times they face are tough times I face.</p><p>My week-to-week work prior to the layoffs is pretty diverse. I adapt to what the organisation needs - a mixture of short term tasks, and long term tasks. When there&#8217;s a problem that I see that we handle reactively, I make a note to try to turn it into something we&#8217;ve approaching proactively. Some things are fine to be reactive to, others require proactive changes to handle better next time. </p><p>These days, it&#8217;s a lot of helping individuals to understand what&#8217;s happening to them. Sometimes people just need someone to talk to. Sometimes people have questions. I don&#8217;t have all the answers, but I can ask questions on their behalf. Sometimes people need honest career advice, which I can do. I would estimate over the last few weeks, I&#8217;ve talked to around 15 people 1-to-1 on average, every day. Sometimes it&#8217;s a lot higher, sometimes it&#8217;s fewer.</p><p>It&#8217;s pretty tiring. I use a lot of my mental energy, so much so that I have no physical energy at the end of every work day. But luckily, because I&#8217;m not too worried about my own job, I can spend that energy helping others.</p><p>Days like this fall into the &#8220;reactive&#8221; category. People come to me, as more information reaches them, and I help them if I can. However, long term, I&#8217;m proactively thinking with two hats on: how can I help employees understand the information they need to make wise decisions, and how can I smooth over the cracks in the emotional safety of the company? </p><p>Some solid anchors I have:</p><ul><li><p>I&#8217;m very passionate about the journalistic mission of the company, and very passionate about the employees.</p></li><li><p>Last time I mapped out the number of employees I&#8217;ve had a meaningful conversation with in the past, it&#8217;s around 250. Those I know well - around 80. Knowing people makes it easier for me to be a sympathetic ear.</p></li><li><p>I know the leaders of the tech organisation well, and trust them - and their passion for employees and the company.</p></li><li><p>I don&#8217;t have any problem challenging others - or raising concerns, which often puts me in a unique position to do so.</p></li></ul><p>That responsibility obviously does not fall only to me. Nor to anyone, in fact. Sometimes, work life is difficult. That&#8217;s the nature of a capitalistic world. If there&#8217;s not enough revenue to cover the jobs we have, then those jobs have to change. </p><p>I like to remind myself of some generalities about the world:  </p><ul><li><p>Most people are good people, who want the same thing. Safety, happiness, and peace for themselves, their family, and their friends.</p></li><li><p>Change is constant, change can be good, change can be bad, but change will always happen. Change is temporary - maybe with long term consequences, but a fork in the road now does not limit the future, much.</p></li><li><p>In the majority of cases, people manage to live good lives. Bad things may happen, but when looking at it from the whole timeline of someone&#8217;s life, things happen to work out somehow.</p></li><li><p>In business, difficult decisions have to be made that people may be unhappy or negatively impacted by. These decisions, in Norway and Sweden, are rarely based on animosity. We have some of the most equal societies in the world - and therefore it&#8217;s not a Meta/Amazon billionaire-CEO situation. </p></li><li><p>Mammals will often stop feeding some of their litter when there are too many for the mother to sustain. If the mother tried to feed them all, then the entire litter may suffer. However, if the mother limits her feeding, then the remaining puppies will survive. In this metaphor, the mother is a company. The litter is the employees. And the milk is the cash-flow of a company. Nobody benefits if the company collapses, or goes bankrupt.</p></li></ul><p>A simplistic drawing, but it represents life well. There are always moments in life that give you a new direction - a new environment. Today you are in a forest, tomorrow a desert. It&#8217;s okay if the road you&#8217;re currently on is rough, or through an area you didn&#8217;t want to be in. One day, it will be a good, well-paved road, in an area you&#8217;ve been dreaming of.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Fs2P!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6259d6-364a-407b-9b6d-0a9d29056d36_1134x628.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Fs2P!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6259d6-364a-407b-9b6d-0a9d29056d36_1134x628.png 424w, https://substackcdn.com/image/fetch/$s_!Fs2P!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6259d6-364a-407b-9b6d-0a9d29056d36_1134x628.png 848w, https://substackcdn.com/image/fetch/$s_!Fs2P!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6259d6-364a-407b-9b6d-0a9d29056d36_1134x628.png 1272w, https://substackcdn.com/image/fetch/$s_!Fs2P!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6259d6-364a-407b-9b6d-0a9d29056d36_1134x628.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Fs2P!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6259d6-364a-407b-9b6d-0a9d29056d36_1134x628.png" width="1134" height="628" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6c6259d6-364a-407b-9b6d-0a9d29056d36_1134x628.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:628,&quot;width&quot;:1134,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:125761,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://thetechenabler.substack.com/i/159508991?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6259d6-364a-407b-9b6d-0a9d29056d36_1134x628.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Fs2P!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6259d6-364a-407b-9b6d-0a9d29056d36_1134x628.png 424w, https://substackcdn.com/image/fetch/$s_!Fs2P!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6259d6-364a-407b-9b6d-0a9d29056d36_1134x628.png 848w, https://substackcdn.com/image/fetch/$s_!Fs2P!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6259d6-364a-407b-9b6d-0a9d29056d36_1134x628.png 1272w, https://substackcdn.com/image/fetch/$s_!Fs2P!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c6259d6-364a-407b-9b6d-0a9d29056d36_1134x628.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>When it comes to my own energy, I&#8217;m tired. These periods have probably been some of the most difficult in my career. But every weekend, I&#8217;ve made sure to do fun things with my loved ones. Each day after work, I relax. I go to the office far longer than I usually would, just being available for people in common areas - but when I go home, I&#8217;m mostly &#8220;done&#8221; for the day. I spend the rest of the day with my loved ones, watching things, writing, coding, playing games, and cooking. Normal things, everyday things.</p><p>Since one of my biggest drivers in life is helping others, I&#8217;m more motivated than ever. Since the world at large is going through a scary, challenging time - I&#8217;m more motivated than ever in our journalistic mission. There are often things you can&#8217;t control, changes you don&#8217;t like. I have control over my own reaction, by taking action, through helping others. I&#8217;ve struggled in the past with needing to be over-prepared for every bad situation, but much like software development, resilience is a crucial skill to have.  </p><p>This morning, on the tram, there was a beautiful pure moment: a woman got up to leave, nearly to the door, when another woman who had been sitting near her began yelling. I, with the other passengers, turned to look at the yelling woman. The exiting woman had forgotten her glove, the yelling woman rushed to give it to her. The tram was just about to leave, the now-gloved woman got off. As the tram departed, the gloved woman stood by the window of the yelling woman, smiling at her with complete warmth. Two strangers, who had a better day as a result of a simple interaction. Life is full of these moments. Small factors that add up, making the world more enjoyable, memorable, and genuine. </p><p>If I can help others find their gloves, then I feel I&#8217;m doing a good job - as an employee, as a colleague, as a friend, and as a human.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/subscribe?"><span>Subscribe now</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thetechenabler.substack.com/p/keeping-your-head-up-during-tough?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thetechenabler.substack.com/p/keeping-your-head-up-during-tough?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p>]]></content:encoded></item></channel></rss>