﻿<?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[Web Development Newsletter by Packt]]></title><description><![CDATA[Join 38,000+ web developers and designers who get weekly insights on web development, web design, frameworks, and tools. Stay updated on JavaScript, React, Angular, Node, and AI-powered development - straight to your feed.]]></description><link>https://packtwebdevpro.substack.com</link><image><url>https://substackcdn.com/image/fetch/$s_!-Epb!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c609e43-4006-496a-9adf-84620ff6b584_500x500.png</url><title>Web Development Newsletter by Packt</title><link>https://packtwebdevpro.substack.com</link></image><generator>Substack</generator><lastBuildDate>Thu, 11 Jun 2026 23:40:00 GMT</lastBuildDate><atom:link href="https://packtwebdevpro.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Packt SecPro]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[webdevpro@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[webdevpro@substack.com]]></itunes:email><itunes:name><![CDATA[Packt]]></itunes:name></itunes:owner><itunes:author><![CDATA[Packt]]></itunes:author><googleplay:owner><![CDATA[webdevpro@substack.com]]></googleplay:owner><googleplay:email><![CDATA[webdevpro@substack.com]]></googleplay:email><googleplay:author><![CDATA[Packt]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[WebDevPro #143: Why Your Microservices Need More Than Round-Robin DNS]]></title><description><![CDATA[Meet the author]]></description><link>https://packtwebdevpro.substack.com/p/webdevpro-143-why-your-microservices</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/webdevpro-143-why-your-microservices</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Mon, 08 Jun 2026 14:02:44 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/894b635a-a7fc-4fbe-be76-a4b1627a6662_207x207.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="callout-block" data-callout="true"><h1 style="text-align: center;"><strong>Meet the author</strong></h1><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!sOc4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5502572-6052-4674-a084-ae1f6007c8b4_207x207.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!sOc4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5502572-6052-4674-a084-ae1f6007c8b4_207x207.jpeg 424w, https://substackcdn.com/image/fetch/$s_!sOc4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5502572-6052-4674-a084-ae1f6007c8b4_207x207.jpeg 848w, https://substackcdn.com/image/fetch/$s_!sOc4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5502572-6052-4674-a084-ae1f6007c8b4_207x207.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!sOc4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5502572-6052-4674-a084-ae1f6007c8b4_207x207.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!sOc4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5502572-6052-4674-a084-ae1f6007c8b4_207x207.jpeg" width="207" height="207" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c5502572-6052-4674-a084-ae1f6007c8b4_207x207.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:207,&quot;width&quot;:207,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!sOc4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5502572-6052-4674-a084-ae1f6007c8b4_207x207.jpeg 424w, https://substackcdn.com/image/fetch/$s_!sOc4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5502572-6052-4674-a084-ae1f6007c8b4_207x207.jpeg 848w, https://substackcdn.com/image/fetch/$s_!sOc4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5502572-6052-4674-a084-ae1f6007c8b4_207x207.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!sOc4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc5502572-6052-4674-a084-ae1f6007c8b4_207x207.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p style="text-align: center;"><sup>This article draws on insights from </sup><strong><sup>Magnus Larsson</sup></strong><sup>, an IT industry veteran who has worked in the field since 1986 and has consulted for major Swedish companies such as Volvo, Ericsson, and AstraZeneca. Earlier in his career, Magnus experienced firsthand the challenges of building distributed systems. Today, many of those challenges can be addressed with open-source tools such as Spring Cloud, Kubernetes, and Istio. Over the past eight years, he has helped customers adopt these technologies and shared his expertise through presentations and blog posts.</sup></p></div><div><hr></div><p>There&#8217;s a moment in almost every distributed systems project where someone asks a completely reasonable question: <em>why can&#8217;t we just use DNS?</em> Every instance of a service registers under the same hostname, the DNS server hands back a list of IPs, clients cycle through them. It sounds elegant. It sounds like a solved problem. And for a while, especially in early-stage systems, it kind of works.</p><p>Then you scale up. Instances start crashing and restarting. Network partitions happen. You add a health check somewhere and realize DNS has no idea whether the IP it just returned belongs to a process that&#8217;s been dead for forty seconds. The elegant solution starts showing its seams.</p><p>This article is about why DNS-based service discovery breaks down in distributed systems, what the failure modes actually look like in practice, and how client-side discovery handles the chaos that DNS was never designed for.</p><p>Before we dig deeper into this, here&#8217;s a TL;DR you&#8217;ll need:</p><ul><li><p><em><strong>&#128314; <a href="https://blog.angular.dev/announcing-angular-v22-c52bb83a4664">Angular v22 is Here</a></strong></em></p></li><li><p><em><strong>&#9889; <a href="https://blog.cloudflare.com/voidzero-joins-cloudflare/">VoidZero Joins Cloudflare</a></strong></em></p></li><li><p><strong>&#128736;&#65039; </strong><em><strong><a href="https://github.blog/changelog/2026-06-02-copilot-sdk-is-now-generally-available/">Copilot SDK is Now GA</a></strong></em></p></li><li><p><strong>&#128216; </strong><em><strong><a href="https://github.com/AllThingsSmitty/typescript-tips-everyone-should-know">TypeScript Tips Everyone Should Know</a></strong></em></p></li><li><p><strong>&#127916; </strong><em><strong><a href="https://www.joshwcomeau.com/animation/css-vs-javascript/">CSS vs. JavaScript Animations</a></strong></em></p></li></ul><h2><strong>The DNS Round-Robin Promise</strong></h2><p>The idea behind round-robin DNS is straightforward. Multiple service instances register under the same DNS name. When a client resolves that name, the DNS server returns a list of IP addresses, one per instance, and the client works through them sequentially. The first request goes to the first IP, the second to the next, and so on. Load is distributed. Everyone goes home happy.</p><p>The problem is that this model is built on an assumption that quietly breaks in dynamic environments: that the list of IP addresses returned by DNS accurately reflects the set of healthy, reachable instances <em>right now</em>.</p><p>In a microservices environment, that assumption fails constantly.</p><h2><strong>What Actually Happens When You Try It</strong></h2><p>To make this concrete, consider a scenario where you scale a service to two instances and ask a dependent service what IPs it sees. DNS returns both. But when you start sending real traffic, you notice something strange: requests keep going to the same instance. The load balancing you expected isn&#8217;t happening.</p><p>This reveals one of DNS&#8217;s fundamental limitations as a load balancer: DNS clients don&#8217;t do per-request round-robin. They ask a DNS server once, get a list, try the first address that works, and then <em>hold onto it</em>. Caching is baked into how DNS works. It&#8217;s a feature for performance, but a liability when you need live instance awareness. Once a client finds a working address, it stops asking.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3rK7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2317514b-e846-4ca2-aad3-6e960f2113e6_624x295.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3rK7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2317514b-e846-4ca2-aad3-6e960f2113e6_624x295.png 424w, https://substackcdn.com/image/fetch/$s_!3rK7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2317514b-e846-4ca2-aad3-6e960f2113e6_624x295.png 848w, https://substackcdn.com/image/fetch/$s_!3rK7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2317514b-e846-4ca2-aad3-6e960f2113e6_624x295.png 1272w, https://substackcdn.com/image/fetch/$s_!3rK7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2317514b-e846-4ca2-aad3-6e960f2113e6_624x295.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3rK7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2317514b-e846-4ca2-aad3-6e960f2113e6_624x295.png" width="624" height="295" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2317514b-e846-4ca2-aad3-6e960f2113e6_624x295.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:295,&quot;width&quot;:624,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;DNS returns both IPs&quot;,&quot;title&quot;:&quot;DNS returns both IPs&quot;,&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="DNS returns both IPs" title="DNS returns both IPs" srcset="https://substackcdn.com/image/fetch/$s_!3rK7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2317514b-e846-4ca2-aad3-6e960f2113e6_624x295.png 424w, https://substackcdn.com/image/fetch/$s_!3rK7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2317514b-e846-4ca2-aad3-6e960f2113e6_624x295.png 848w, https://substackcdn.com/image/fetch/$s_!3rK7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2317514b-e846-4ca2-aad3-6e960f2113e6_624x295.png 1272w, https://substackcdn.com/image/fetch/$s_!3rK7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2317514b-e846-4ca2-aad3-6e960f2113e6_624x295.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>That&#8217;s problem one. Problem two is what happens when an instance disappears.</p><h2><strong>The Staleness Problem</strong></h2><p>DNS records have a time-to-live (TTL), and until that TTL expires, clients are working from a cached snapshot of the world. If an instance crashes, DNS doesn&#8217;t know. If a new instance starts up, DNS doesn&#8217;t know that either, not until someone updates the record and the TTL rolls over. In a system where instances come and go every few minutes, even a 30-second TTL creates meaningful windows of failure.</p><p>More critically, DNS has no concept of health. An IP address in a DNS response is just an IP address. It carries no information about whether the process listening there is actually ready to handle requests, whether it&#8217;s mid-restart, or whether it&#8217;s responding to health checks but silently dropping traffic due to a downstream issue. DNS cannot answer the question &#8220;is this instance okay?&#8221; because it was never designed to.</p><h2><strong>The Challenges DNS Can&#8217;t Address</strong></h2><p>When you enumerate what a robust service discovery mechanism actually needs to handle, the gap becomes clear.</p><p>New instances can appear at any time and need to be made available to clients quickly, not after a TTL expires. Existing instances can fail at any time, and failed instances need to be removed from rotation just as quickly. Some instances that fail temporarily might recover and should rejoin rotation; others won&#8217;t and should be permanently deregistered. New instances often have startup time as well. They can accept TCP connections before they&#8217;re actually ready to serve traffic, which means &#8220;is the port open&#8221; is a poor proxy for &#8220;is this instance ready.&#8221; And unintended network partitions, where a client loses connectivity to some instances but not others, can cause cascading failures if the discovery layer doesn&#8217;t account for them.</p><p>None of these are edge cases. They&#8217;re the normal operating conditions of a distributed system at any meaningful scale.</p><h2><strong>Client-Side Discovery: A Different Model</strong></h2><p>The approach taken by systems like Netflix Eureka flips the model. Rather than relying on DNS as a passive lookup table, it introduces an active registry that instances communicate with continuously.</p><p>When a service instance starts, it registers itself with the discovery server, not just its address but information about what it is. On a regular interval, it sends a heartbeat to signal that it&#8217;s still alive and healthy. If the heartbeats stop, the discovery server removes the instance from the registry after a configurable window. Clients, meanwhile, periodically fetch the current registry from the discovery server and cache it locally. When a client needs to make a call, it already has a fresh list of available instances and can select one without making a synchronous request to the discovery service for every call.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8iLP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3495966-e538-42ee-bdc9-f218777b7ebb_624x312.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8iLP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3495966-e538-42ee-bdc9-f218777b7ebb_624x312.png 424w, https://substackcdn.com/image/fetch/$s_!8iLP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3495966-e538-42ee-bdc9-f218777b7ebb_624x312.png 848w, https://substackcdn.com/image/fetch/$s_!8iLP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3495966-e538-42ee-bdc9-f218777b7ebb_624x312.png 1272w, https://substackcdn.com/image/fetch/$s_!8iLP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3495966-e538-42ee-bdc9-f218777b7ebb_624x312.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8iLP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3495966-e538-42ee-bdc9-f218777b7ebb_624x312.png" width="624" height="312" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c3495966-e538-42ee-bdc9-f218777b7ebb_624x312.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:312,&quot;width&quot;:624,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!8iLP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3495966-e538-42ee-bdc9-f218777b7ebb_624x312.png 424w, https://substackcdn.com/image/fetch/$s_!8iLP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3495966-e538-42ee-bdc9-f218777b7ebb_624x312.png 848w, https://substackcdn.com/image/fetch/$s_!8iLP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3495966-e538-42ee-bdc9-f218777b7ebb_624x312.png 1272w, https://substackcdn.com/image/fetch/$s_!8iLP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3495966-e538-42ee-bdc9-f218777b7ebb_624x312.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>This architecture gets several things right that DNS doesn&#8217;t.</p><ul><li><p><strong>Instance registration is active, not passive.</strong> A service has to deliberately register itself, and it has to keep proving it&#8217;s alive through heartbeats. An instance that crashes stops sending heartbeats and gets removed from the registry. There&#8217;s no waiting for a TTL.</p></li><li><p><strong>Readiness is separable from availability.</strong> A service can control when it registers itself, after initialization is complete, after database connections are established, after whatever startup work needs to happen. The registry reflects intent, not just the existence of a listening port.</p></li><li><p><strong>Clients are participants, not observers.</strong> Because clients cache the registry locally and refresh it on a schedule, they can make load-balancing decisions with reasonably current information, and they do so per-request rather than per-connection. This is what produces actual round-robin behavior in practice.</p></li><li><p><strong>The system degrades gracefully.</strong> If the discovery server itself goes down, clients continue operating from their local cache. They can still reach instances that were registered before the outage. New instances can&#8217;t register and deregistered instances won&#8217;t be removed, but existing traffic keeps flowing. If a DNS server goes down, resolution fails entirely.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!sZ74!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffece6e7f-8864-44eb-85a5-b251d70ac8d8_624x260.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!sZ74!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffece6e7f-8864-44eb-85a5-b251d70ac8d8_624x260.png 424w, https://substackcdn.com/image/fetch/$s_!sZ74!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffece6e7f-8864-44eb-85a5-b251d70ac8d8_624x260.png 848w, https://substackcdn.com/image/fetch/$s_!sZ74!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffece6e7f-8864-44eb-85a5-b251d70ac8d8_624x260.png 1272w, https://substackcdn.com/image/fetch/$s_!sZ74!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffece6e7f-8864-44eb-85a5-b251d70ac8d8_624x260.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!sZ74!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffece6e7f-8864-44eb-85a5-b251d70ac8d8_624x260.png" width="624" height="260" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fece6e7f-8864-44eb-85a5-b251d70ac8d8_624x260.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:260,&quot;width&quot;:624,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!sZ74!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffece6e7f-8864-44eb-85a5-b251d70ac8d8_624x260.png 424w, https://substackcdn.com/image/fetch/$s_!sZ74!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffece6e7f-8864-44eb-85a5-b251d70ac8d8_624x260.png 848w, https://substackcdn.com/image/fetch/$s_!sZ74!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffece6e7f-8864-44eb-85a5-b251d70ac8d8_624x260.png 1272w, https://substackcdn.com/image/fetch/$s_!sZ74!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffece6e7f-8864-44eb-85a5-b251d70ac8d8_624x260.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><h2><strong>The Propagation Question</strong></h2><p>One nuance worth understanding is that client-side discovery still has propagation delay. It&#8217;s just controlled and predictable rather than dependent on TTLs set by infrastructure you may not own.</p><p>When an instance spins up and registers, clients that have already fetched the registry won&#8217;t know about it until their next refresh cycle. Similarly, when an instance goes down, there&#8217;s a window between the last heartbeat and the next client cache refresh during which they might try to call an address that no longer works. This is why production systems built on client-side discovery pair it with retry logic and circuit breakers. The discovery layer reduces the failure surface significantly, but it doesn&#8217;t eliminate the need for resilience patterns at the call level.</p><p>The important difference from DNS is that these windows are tunable. In a development environment, you might configure clients to refresh every five seconds and instances to send heartbeats just as frequently. In production, you&#8217;d balance freshness against the load of constant registry polling. DNS gives you no such control.</p><h2><strong>What This Means in Practice</strong></h2><p>The practical implication of all this is that service discovery isn&#8217;t primarily a load balancing problem. It&#8217;s a <em>membership</em> problem. The question being answered is &#8220;who is currently in this service&#8217;s pool of healthy instances?&#8221; and DNS was built for a world where membership changes on a timescale of hours or days, not seconds or minutes.</p><p>Client-side discovery systems treat membership as a live, continuously updated data structure. Instances opt in by registering and staying registered through heartbeats. Clients subscribe to changes in that membership by periodically refreshing their local view. The discovery server is the source of truth, but it&#8217;s a source of truth that expects the world to change constantly and is designed accordingly.</p><p>When you start thinking about service discovery through this lens, as a membership system rather than a name resolution system, the limitations of DNS become obvious. DNS is a remarkably well-engineered solution to the problem it was designed to solve. Service discovery in distributed systems is a different problem entirely.</p><h2><strong>Takeaways</strong></h2><ul><li><p><strong>DNS round-robin doesn&#8217;t actually round-robin.</strong> Clients cache working addresses and stick with them. The per-request load distribution you expect doesn&#8217;t happen in practice.</p></li><li><p><strong>DNS has no health awareness.</strong> An IP in a DNS response carries no signal about whether that instance is alive, ready, or functional. Health and availability are entirely separate concerns that DNS has no mechanism to represent.</p></li><li><p><strong>Instance registration needs to be active, not passive.</strong> Robust service discovery requires instances to continuously prove they&#8217;re alive, not just appear in a record once. Heartbeat-based registration is the mechanism that makes deregistration automatic and timely.</p></li><li><p><strong>Propagation delay exists in all discovery systems, but client-side discovery makes it controllable.</strong> Understanding the refresh window and pairing discovery with retry logic is the path to resilient service-to-service communication.</p></li><li><p><strong>The discovery server is not a single point of failure if clients cache.</strong> Because clients maintain local copies of the registry, discovery server downtime degrades gracefully rather than catastrophically, a significant practical advantage over centralized DNS in high-availability requirements.</p></li></ul><p>Service discovery isn&#8217;t glamorous infrastructure. It&#8217;s the kind of thing that works invisibly when it&#8217;s right and causes deeply confusing failures when it&#8217;s wrong. Getting the model right from the start saves a lot of painful debugging later.</p><h1 style="text-align: center;"><strong>This Week in the News</strong></h1><ul><li><p><strong>&#9889; <a href="https://blog.cloudflare.com/voidzero-joins-cloudflare/">VoidZero Joins Cloudflare</a></strong>: Big news: Cloudflare has acquired VoidZero, the team behind Vite, Vitest, Rolldown, and Oxc, and has pledged $1 million to an independent Vite ecosystem fund. Evan You was frank about the reason: monetizing open-source tooling has proven extremely hard, despite Vite&#8217;s enormous adoption. Vite stays MIT-licensed and vendor-neutral, but Cloudflare now has its hands on the plumbing of a large chunk of the modern web. Worth watching closely.</p></li><li><p><strong>&#128314; <a href="https://blog.angular.dev/announcing-angular-v22-c52bb83a4664">Angular v22 is Here</a></strong>: The signal-first era is no longer a roadmap promise. Signal Forms and resources are now stable, OnPush is now the default change detection strategy, and the HTTP client uses Fetch by default. This is a consolidation release: the experiments are over, and you&#8217;re looking at the Angular team&#8217;s considered view of how production apps should be built in 2026. If you&#8217;ve been waiting for the right time to migrate, that time is now.</p></li><li><p><strong>&#9760;&#65039; <a href="https://arstechnica.com/security/2026/06/dozens-of-red-hat-packages-backdoored-through-its-offical-npm-channel/">Red Hat&#8217;s npm Namespace Got Backdoored</a></strong>: A compromised Red Hat employee GitHub account was used to inject malicious workflows into three RedHatInsights repositories, with OIDC tokens publishing backdoored package versions that carried valid SLSA provenance attestations, making them look completely legitimate. The worm self-propagates using stolen npm tokens, bypassing 2FA to republish backdoored versions of other packages autonomously. This one is nasty. If you ran npm install on anything under @redhat-cloud-services after June 1st, rotate everything.</p></li><li><p><strong>&#129505; <a href="https://svelte.dev/blog/whats-new-in-svelte-june-2026">What&#8217;s New in Svelte: June 2026</a></strong>: This month brings better forms, new long-lived remote query APIs, and TypeScript 6 support in language-tools. The standout addition is .live(...), a new query function that makes pulling real-time server data dramatically cleaner. Svelte&#8217;s changelog keeps getting better without the drama. Quiet excellence.</p></li><li><p><strong>&#129302; <a href="https://2026.stateofai.dev/en-US">State of AI 2026</a></strong>: Devographics surveyed 7,258 developers on AI in their workflows, and the numbers are striking. The average proportion of AI-generated code has jumped from 28% in 2025 to 54% this year, with the 75%+ segments seeing the highest growth. ChatGPT leads in raw usage, but Claude tops the charts for positive sentiment and is the model developers are most willing to actually pay for. The full dataset is worth digging into; pull up the interactive charts.</p></li><li><p><strong>&#128736;&#65039; <a href="https://github.blog/changelog/2026-06-02-copilot-sdk-is-now-generally-available/">Copilot SDK is Now GA</a></strong>: You can now embed GitHub Copilot&#8217;s agentic engine directly into your own applications and developer tools, with access to planning, tool invocation, file edits, streaming, and multi-turn sessions, no need to build your own orchestration layer. Support spans Node.js, Python, Go, .NET, Rust, and Java. This is less a Copilot story and more a platform story; GitHub is positioning itself as the runtime for AI-native dev tooling.</p></li></ul><h1 style="text-align: center;"><strong>Beyond the Headlines</strong></h1><ul><li><p><strong>&#129504; <a href="https://addyosmani.com/blog/orchestration-tax">The Orchestration Tax</a></strong>: Addy Osmani names something most of us are quietly struggling with: spinning up more agents doesn&#8217;t mean you&#8217;re doing more. Your cognitive bandwidth doesn&#8217;t parallelize. All the judgment to actually steer agents and merge the code they produce still has to route through exactly one serial processor, which is you. Feeling busy is not the same as being productive.</p></li><li><p><strong>&#128216; <a href="https://github.com/AllThingsSmitty/typescript-tips-everyone-should-know">TypeScript Tips Everyone Should Know</a></strong>: This is a compact, no-nonsense reference of TypeScript patterns worth bookmarking. Solid for both onboarding newer devs and as a quick refresh, the kind of thing that pays dividends when you actually internalize it rather than skim it once and forget.</p></li><li><p><strong>&#127757; <a href="https://drfeifei.substack.com/p/a-functional-taxonomy-of-world-models">A Functional Taxonomy of World Models</a></strong>: Fei-Fei Li and the World Labs team cut through the noise around &#8220;world models&#8221; and actually define what the term means across different fields. Computer vision, robotics, reinforcement learning, and generative AI all claim to be building world models, and each means something quite different: renderers, simulators, planners. If you care about where AI is actually heading beyond LLMs, this is essential reading.</p></li><li><p><strong>&#9203; <a href="https://jjenzz.com/best-loading-states-are-no-loading-states">The Best Loading States Are No Loading States</a></strong>: Applications end up with skeletons, spinners, shimmer effects, suspense fallbacks, UI whose only job is to occupy the space where data should eventually appear. We&#8217;re all spending a surprising amount of time solving the same problem, and none of it is really product work. This is a sharp essay that argues we&#8217;ve been thinking about this backwards, and the web already had the answer before SPAs came along.</p></li><li><p><strong>&#127916; <a href="https://www.joshwcomeau.com/animation/css-vs-javascript/">CSS vs. JavaScript Animations</a>:</strong> Josh Comeau compares the same animations built across several different strategies and examines the performance implications firsthand, and there&#8217;s some interesting nuance in the results. Not the take you might expect. This is a required reading before you reach for a JS animation library by default.</p></li><li><p><strong>&#128257; <a href="https://www.anthropic.com/institute/recursive-self-improvement">When AI Builds Itself</a></strong>: The Anthropic Institute published something worth sitting with: a look at their actual progress toward recursive self-improvement, with internal data included. Anthropic engineers today ship 8x as much code per quarter as they did between 2021 and 2025, and a growing share of the AI development cycle is now being delegated to AI systems themselves. They&#8217;re careful to say recursive self-improvement isn&#8217;t inevitable, but the framing is unusually candid.</p></li></ul><h1 style="text-align: center;"><strong>The Developer Toolbox</strong></h1><p><strong>&#9997;&#65039; <a href="https://tiptap.dev/docs/hocuspocus/getting-started/overview">Hocuspocus</a></strong></p><p>If you need to add real-time collaborative editing to an app, Hocuspocus from the Tiptap team is the cleanest path there. It&#8217;s a plug-and-play collaboration backend based on Y.js, handling conflict resolution via CRDT so you don&#8217;t have to think about merge logic. Works offline, syncs on reconnect, and pairs naturally with Tiptap, but it&#8217;s flexible enough for other editors too.</p><p><em>That&#8217;s all for this week. Have any ideas you want to see in the next article? Hit Reply!</em></p><p>Cheers!</p><p>Editor-in-chief,</p><p>Kinnari Chohan</p><div><hr></div><p><strong>&#128075; <a href="https://landing.packtpub.com/sponsorship-landing-page/">Advertise with us</a></strong><br><strong> </strong>Interested in sponsoring this newsletter and reaching a highly engaged audience of tech professionals? Simply reply to this email, and our team will get in touch with the next steps.</p>]]></content:encoded></item><item><title><![CDATA[WebDevPro #142 Thinking in Transitions: The mental shift React 19 makes hard to ignore ]]></title><description><![CDATA[Grow your Mac app with Setapp.]]></description><link>https://packtwebdevpro.substack.com/p/webdevpro-142-thinking-in-transitions</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/webdevpro-142-thinking-in-transitions</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Mon, 01 Jun 2026 14:03:16 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!rJQG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d693bf4-0953-48f8-b71b-61b850cda8d7_400x600.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="callout-block" data-callout="true"><h1 style="text-align: center;"><strong><a href="https://www.vpdae.com/redirect/7kj4k0cgrz8inirkn90zgt5dur3">Grow your Mac app with Setapp. Get around 30K unique impressions in the first days after your app&#8217;s release</a></strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rJQG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d693bf4-0953-48f8-b71b-61b850cda8d7_400x600.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rJQG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d693bf4-0953-48f8-b71b-61b850cda8d7_400x600.png 424w, https://substackcdn.com/image/fetch/$s_!rJQG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d693bf4-0953-48f8-b71b-61b850cda8d7_400x600.png 848w, https://substackcdn.com/image/fetch/$s_!rJQG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d693bf4-0953-48f8-b71b-61b850cda8d7_400x600.png 1272w, https://substackcdn.com/image/fetch/$s_!rJQG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d693bf4-0953-48f8-b71b-61b850cda8d7_400x600.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rJQG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d693bf4-0953-48f8-b71b-61b850cda8d7_400x600.png" width="246" height="369" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6d693bf4-0953-48f8-b71b-61b850cda8d7_400x600.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:600,&quot;width&quot;:400,&quot;resizeWidth&quot;:246,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!rJQG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d693bf4-0953-48f8-b71b-61b850cda8d7_400x600.png 424w, https://substackcdn.com/image/fetch/$s_!rJQG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d693bf4-0953-48f8-b71b-61b850cda8d7_400x600.png 848w, https://substackcdn.com/image/fetch/$s_!rJQG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d693bf4-0953-48f8-b71b-61b850cda8d7_400x600.png 1272w, https://substackcdn.com/image/fetch/$s_!rJQG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d693bf4-0953-48f8-b71b-61b850cda8d7_400x600.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>Setapp makes sure your app isn&#8217;t just listed, but seen. Plus, we handle the stuff you don&#8217;t like: distribution, licensing, billing, taxes, and customer support. You build great software; we bring you revenue and valuable feedback to help your app grow. Hope is not a growth strategy. Join Setapp. <strong><a href="https://www.vpdae.com/redirect/7kj4k0cgrz8inirkn90zgt5dur3">Share your app</a>!</strong></p></div><div><hr></div><div class="callout-block" data-callout="true"><h1><strong>Meet the author</strong></h1><p><strong>This piece is written by Rodrigo Lobenwein</strong>. </p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!40oK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ddd27ae-71a6-4636-b1e2-4c769139d8ab_398x398.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!40oK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ddd27ae-71a6-4636-b1e2-4c769139d8ab_398x398.png 424w, https://substackcdn.com/image/fetch/$s_!40oK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ddd27ae-71a6-4636-b1e2-4c769139d8ab_398x398.png 848w, https://substackcdn.com/image/fetch/$s_!40oK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ddd27ae-71a6-4636-b1e2-4c769139d8ab_398x398.png 1272w, https://substackcdn.com/image/fetch/$s_!40oK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ddd27ae-71a6-4636-b1e2-4c769139d8ab_398x398.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!40oK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ddd27ae-71a6-4636-b1e2-4c769139d8ab_398x398.png" width="212" height="212" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8ddd27ae-71a6-4636-b1e2-4c769139d8ab_398x398.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:398,&quot;width&quot;:398,&quot;resizeWidth&quot;:212,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!40oK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ddd27ae-71a6-4636-b1e2-4c769139d8ab_398x398.png 424w, https://substackcdn.com/image/fetch/$s_!40oK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ddd27ae-71a6-4636-b1e2-4c769139d8ab_398x398.png 848w, https://substackcdn.com/image/fetch/$s_!40oK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ddd27ae-71a6-4636-b1e2-4c769139d8ab_398x398.png 1272w, https://substackcdn.com/image/fetch/$s_!40oK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ddd27ae-71a6-4636-b1e2-4c769139d8ab_398x398.png 1456w" sizes="100vw"></picture><div></div></div></a></figure></div><p>With a background in full stack development across .NET and React, Rodrigo leads a team of senior developers and QA specialists, focusing on the architectural decisions that sit between engineering and product.</p><p>His work centers on helping teams develop the judgment to make the right technical calls not just follow the right frameworks.</p></div><p>React developers learn a reliable reflex early on: update state, let the component re-render, trust the output. That model still holds. The friction starts when the work behind a state update grows large enough for users to actually feel it: a search input that lags on every keystroke while thousands of rows refilter behind it, a tab change that completes instantly in the code but arrives just late enough to make the UI feel sluggish.</p><p>The instinct at that point is to reach for <strong>useMemo</strong> or <strong>useCallback</strong>. Those tools still matter, but they address unnecessary work. Sometimes the problem is different: React is being asked to treat urgent and non-urgent work as if they carry equal weight. Since version 18, the framework has had a better vocabulary for that distinction, and React 19 extends it further. Developing an intuition for when to apply it is what this piece is about.</p><p>Before we dig deeper into this, here&#8217;s a TL;DR you need:</p><ul><li><p><strong>&#129302; <a href="https://blog.google/innovation-and-ai/technology/ai/google-io-2026-all-our-announcements/">Google I/O 2026 pushes deeper into the agentic AI era</a></strong></p></li><li><p><strong>&#128218; <a href="https://storybook.js.org/blog/storybook-10-4/">Storybook 10.4 brings improvements for component-driven development</a></strong></p></li><li><p><strong>&#129513; <a href="https://aurorascharff.no/posts/component-architecture-for-react-server-components/">Designing component architecture for React Server Components</a></strong></p></li><li><p><strong>&#128640; <a href="https://javascript.plainenglish.io/migrating-express-to-next-js-using-ai-agents-antigravity-f48b4c206a8e">Migrating from Express to Next.js with AI agents</a></strong></p></li><li><p><strong>&#128506;&#65039; <a href="https://cassidoo.co/post/clustering-tiles/">What clustering map tiles can teach us about problem solving</a></strong></p></li></ul><h2><strong>Not Every Update Has the Same Urgency</strong></h2><p>Consider a search screen. A user types a character into an input. Two things happen simultaneously: the text field shows the new value, and the results list re-renders against the new query.</p><p>Those updates are related but not equally pressing. The input sits directly under the user&#8217;s fingers &#8212; any delay there registers immediately as a broken experience. The results list matters too, but a brief lag is far less perceptible than a laggy cursor. Most users won&#8217;t notice 100ms of stale results. They will notice 100ms of input latency.</p><blockquote><p><em>Instead of thinking only in terms of &#8220;state changed, render now,&#8221; concurrent React asks you to think about which update is urgent and which can wait for a better moment.</em></p></blockquote><p>That distinction is the conceptual foundation of concurrent rendering.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gqVy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe59ecd24-ae4d-4f96-81d5-9f21318eff94_540x185.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gqVy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe59ecd24-ae4d-4f96-81d5-9f21318eff94_540x185.png 424w, https://substackcdn.com/image/fetch/$s_!gqVy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe59ecd24-ae4d-4f96-81d5-9f21318eff94_540x185.png 848w, https://substackcdn.com/image/fetch/$s_!gqVy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe59ecd24-ae4d-4f96-81d5-9f21318eff94_540x185.png 1272w, https://substackcdn.com/image/fetch/$s_!gqVy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe59ecd24-ae4d-4f96-81d5-9f21318eff94_540x185.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gqVy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe59ecd24-ae4d-4f96-81d5-9f21318eff94_540x185.png" width="540" height="185" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e59ecd24-ae4d-4f96-81d5-9f21318eff94_540x185.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:185,&quot;width&quot;:540,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!gqVy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe59ecd24-ae4d-4f96-81d5-9f21318eff94_540x185.png 424w, https://substackcdn.com/image/fetch/$s_!gqVy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe59ecd24-ae4d-4f96-81d5-9f21318eff94_540x185.png 848w, https://substackcdn.com/image/fetch/$s_!gqVy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe59ecd24-ae4d-4f96-81d5-9f21318eff94_540x185.png 1272w, https://substackcdn.com/image/fetch/$s_!gqVy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe59ecd24-ae4d-4f96-81d5-9f21318eff94_540x185.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p style="text-align: center;"><em>Figure 1 - The two tiers of update urgency in concurrent React</em></p><h2><strong>What Automatic Batching Actually Solved</strong></h2><p>Before transitions make sense, it helps to separate them from automatic batching, which is an adjacent improvement that solves a different problem.</p><p>In React 17, batching was largely confined to synchronous React event handlers. Multiple state updates inside a Promise callback, a <strong>setTimeout</strong>, or a <strong>fetch</strong> response were often processed as separate renders. More renders than necessary, without much upside.</p><p>The <strong>createRoot</strong> API in version 18 extended automatic batching across more update sources: timers, Promise handlers, and most async callbacks. Many apps shed redundant render cycles without changing a single component.</p><p>Batching is a reduction in render quantity. Transitions are about render priority. Even with batching in place, a single batched update that includes expensive list rendering can make an input feel sticky. Batching has no way to distinguish which part of that update the user is waiting on. Transitions provide that signal.</p><h2><strong>Marking Lower-Priority Work with startTransition</strong></h2><p>The <strong>startTransition</strong> API lets you label a state update as non-urgent. &#8220;Non-urgent&#8221; does not mean &#8220;unimportant&#8221; &#8212; it means React does not need to hold up higher-priority feedback to process it first.</p><p>In a search interface, the pattern looks like this:</p><p><code>const handleOnChange = (event) =&gt; {</code></p><p><code>setInputValue(event.target.value); // urgent: runs first</code></p><p><code>startTransition(() =&gt; {</code></p><p><code>setQuery(event.target.value); // deferred: can wait</code></p><p><code>});</code></p><p><code>};</code></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!O3sN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb6a6ba7-cefb-414c-ba8e-29d62dc531ed_617x243.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!O3sN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb6a6ba7-cefb-414c-ba8e-29d62dc531ed_617x243.png 424w, https://substackcdn.com/image/fetch/$s_!O3sN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb6a6ba7-cefb-414c-ba8e-29d62dc531ed_617x243.png 848w, https://substackcdn.com/image/fetch/$s_!O3sN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb6a6ba7-cefb-414c-ba8e-29d62dc531ed_617x243.png 1272w, https://substackcdn.com/image/fetch/$s_!O3sN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb6a6ba7-cefb-414c-ba8e-29d62dc531ed_617x243.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!O3sN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb6a6ba7-cefb-414c-ba8e-29d62dc531ed_617x243.png" width="617" height="243" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cb6a6ba7-cefb-414c-ba8e-29d62dc531ed_617x243.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:243,&quot;width&quot;:617,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!O3sN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb6a6ba7-cefb-414c-ba8e-29d62dc531ed_617x243.png 424w, https://substackcdn.com/image/fetch/$s_!O3sN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb6a6ba7-cefb-414c-ba8e-29d62dc531ed_617x243.png 848w, https://substackcdn.com/image/fetch/$s_!O3sN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb6a6ba7-cefb-414c-ba8e-29d62dc531ed_617x243.png 1272w, https://substackcdn.com/image/fetch/$s_!O3sN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb6a6ba7-cefb-414c-ba8e-29d62dc531ed_617x243.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 style="text-align: center;"><em>Figure 2 &#8212; Without transitions, an expensive list render blocks the input. With transitions, the input stays instant and list work is interruptible.</em></p><p>The transition wraps the update that causes the expensive rendering, not the expensive code itself. React is not being told to skip the work; it&#8217;s being given the context to sequence it correctly.</p><p>A reliable heuristic: reach for a transition when a state update can trigger a large render, and the user does not need to see the result of that update instantaneously. Filtering a long list is a candidate. Updating the visible value in an input is not.</p><p>When the UI needs to acknowledge that transition work is still in progress, <strong>useTransition</strong> returns both pieces:</p><p><code>const [isPending, startTransition] = useTransition();</code></p><p>Use <strong>isPending</strong> for lightweight signals: dimming stale content, showing a small spinner. Resist the urge to let it take over the layout, its value is in supporting the interaction, not replacing it.</p><h2><strong>When useDeferredValue Fits Better</strong></h2><p>Both <strong>startTransition</strong> and <strong>useDeferredValue</strong> address the same class of problem. The choice between them turns on where you have control in the component tree.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ZGgK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52e55659-fd19-4886-a537-8a0c23a3384f_586x252.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZGgK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52e55659-fd19-4886-a537-8a0c23a3384f_586x252.png 424w, https://substackcdn.com/image/fetch/$s_!ZGgK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52e55659-fd19-4886-a537-8a0c23a3384f_586x252.png 848w, https://substackcdn.com/image/fetch/$s_!ZGgK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52e55659-fd19-4886-a537-8a0c23a3384f_586x252.png 1272w, https://substackcdn.com/image/fetch/$s_!ZGgK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52e55659-fd19-4886-a537-8a0c23a3384f_586x252.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZGgK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52e55659-fd19-4886-a537-8a0c23a3384f_586x252.png" width="586" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/52e55659-fd19-4886-a537-8a0c23a3384f_586x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:586,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!ZGgK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52e55659-fd19-4886-a537-8a0c23a3384f_586x252.png 424w, https://substackcdn.com/image/fetch/$s_!ZGgK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52e55659-fd19-4886-a537-8a0c23a3384f_586x252.png 848w, https://substackcdn.com/image/fetch/$s_!ZGgK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52e55659-fd19-4886-a537-8a0c23a3384f_586x252.png 1272w, https://substackcdn.com/image/fetch/$s_!ZGgK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52e55659-fd19-4886-a537-8a0c23a3384f_586x252.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 style="text-align: center;"><em>Figure 3 &#8212; The decision comes down to code ownership. Both APIs produce equivalent scheduling outcomes</em></p><p>When the component owns both the input and the expensive update, <strong>startTransition</strong> is usually the cleaner solution:</p><p><code>function SearchPage() {</code></p><p><code>const [inputValue, setInputValue] = useState(&#8221;&#8220;);</code></p><p><code>const [query, setQuery] = useState(&#8221;&#8220;);</code></p><p><code>const [isPending, startTransition] = useTransition();</code></p><p><code>const handleOnChange = (event) =&gt; {</code></p><p><code>const nextValue = event.target.value;</code></p><p><code>setInputValue(nextValue);</code></p><p><code>startTransition(() =&gt; { setQuery(nextValue); });</code></p><p><code>};</code></p><p><code>return (</code></p><p><code>&lt;&gt;</code></p><p><code>&lt;input value={inputValue} onChange={handleOnChange} /&gt;</code></p><p><code>&lt;Results query={query} dimmed={isPending} /&gt;</code></p><p><code>&lt;/&gt;</code></p><p><code>);</code></p><p><code>}</code></p><p>The component has direct access to both setState calls, so it can be explicit about which one should yield.</p><p>When the value arrives from outside, from a parent, a form library, route state, or a shared component, the results component can&#8217;t reach the original setState. It can, however, choose to render against a deferred version of the value:</p><p><code>function ResultsPanel({ query }) {</code></p><p><code>const deferredQuery = useDeferredValue(query);</code></p><p><code>const isStale = query !== deferredQuery;</code></p><p><code>const items = useMemo(</code></p><p><code>() =&gt; filterLargeList(deferredQuery),</code></p><p><code>[deferredQuery]</code></p><p><code>);</code></p><p><code>return &lt;Results items={items} dimmed={isStale} /&gt;;</code></p><p><code>}</code></p><p>Here, <strong>query</strong> updates immediately in the parent; <strong>deferredQuery</strong> trails behind when rendering is busy. The expensive filtering follows the deferred value, so the input stays responsive regardless of how long the results take.</p><h2><strong>How This Changes Component Design</strong></h2><p>Concurrent rendering does not mean every piece of state needs a priority label. Most updates are cheap, and most components need no transitions whatsoever.</p><p>The practical design question is more targeted: what part of this interaction must feel instant, and what part can follow slightly behind? Asking it tends to clarify both component boundaries and state placement. State driving the element the user is actively touching belongs on the urgent path. State driving a large subtree, expensive filtering, or a complex visual transformation is often a better fit for transition work.</p><p>One underrated benefit of this model is interruptibility. Transition rendering can be abandoned. If a user types another character before the previous results render finishes, React discards the stale render and restarts with the latest input. That&#8217;s a meaningful improvement over older <strong>setTimeout</strong>-based workarounds, where React had no clear signal about which work was still relevant.</p><h2><strong>The Shift Worth Internalizing</strong></h2><p>The APIs themselves are small. <strong>startTransition</strong> wraps a state update. <strong>useDeferredValue</strong> returns a lagging version of a value. The more durable change is in how you reason about responsiveness.</p><p>Older React code tends to treat rendering as a single block: state changes, render fires, UI reflects the result. Concurrent React asks for a slightly different mental model &#8212; one closer to how interface designers think about interaction. The thing under the user&#8217;s control responds first. Work that improves the screen but doesn&#8217;t need to be immediate follows behind.</p><blockquote><p><em>React performance is not only about preventing work. It is also about sequencing work so the app feels responsive where it matters most.</em></p></blockquote><h2><strong>Key Takeaways</strong></h2><ul><li><p>React 18 expanded automatic batching via <strong>createRoot</strong>, cutting unnecessary renders across async update sources.</p></li><li><p><strong>startTransition</strong> schedules a state update as lower priority without preventing it from running.</p></li><li><p><strong>useTransition</strong> returns <strong>[isPending, startTransition]</strong>, letting you give subtle in-progress feedback while expensive work continues.</p></li><li><p><strong>useDeferredValue</strong> fits when a component receives a value from outside and can tolerate rendering against a slightly older version.</p></li><li><p>Transition rendering is interruptible &#8212; stale work is abandoned when newer, more urgent updates arrive.</p></li><li><p>The concurrent model reframes performance: not only as avoiding unnecessary work, but as sequencing necessary work by urgency.</p></li></ul><p><em>Want to read more on the topic? <a href="https://www.amazon.com/React-Native-cross-platform-JavaScript-TypeScript/dp/1837020299/ref=sr_1_1_sspa">React and React Native, Sixth Edition</a> covers React 19 and React Native from the ground up.</em></p><div><hr></div><div class="callout-block" data-callout="true"><p><strong>&#127873; GIVEAWAY &#8212; JUNE 2026</strong></p><h2><strong>Build AI Products Faster with Cursor, Lovable &amp; Windsurf</strong></h2><p>Subscribe to <strong><a href="https://packtbuildwithai.substack.com/">BuildWithAI</a></strong> and get our complete <em><strong>Vibe Coding with Cursor, Windsurf, and Lovable</strong></em> delivered free to your inbox. </p><p>Learn the exact workflows builders are using to:</p><p>     &#9989; Turn ideas into working products in hours</p><p>     &#9989; Build MVPs without getting stuck in code</p><p>     &#9989; Use Cursor, Lovable &amp; Windsurf effectively together</p><p>     &#9989; Launch faster with AI-assisted development</p></div><div><hr></div><h1 style="text-align: center;"><strong>This Week in the News</strong></h1><ul><li><p><strong>&#129302; <a href="https://blog.google/innovation-and-ai/technology/ai/google-io-2026-all-our-announcements/">Google I/O 2026 pushes deeper into the agentic AI era</a></strong>: Google used I/O 2026 to double down on AI across its entire ecosystem, with major updates to Gemini, Search, developer tools, and agent-based workflows. The company introduced new models like Gemini Omni and Gemini 3.5 Flash, expanded its agent platform, and continued reshaping Search around AI-powered experiences. The bigger theme was clear: Google is moving beyond AI as a feature and positioning it as the foundation across products, workflows, and developer tooling.</p></li><li><p><strong>&#128218; <a href="https://storybook.js.org/blog/storybook-10-4/">Storybook 10.4 brings improvements for component-driven development</a>: Storybook 10.4</strong> introduces a range of updates aimed at improving the developer experience around building, testing, and documenting UI components. The release continues Storybook&#8217;s focus on making component-driven development more efficient, with enhancements across workflows, tooling, and framework support. As frontend applications grow in complexity, tools like Storybook are becoming increasingly important for maintaining consistency and speeding up UI development.</p></li><li><p>&#128640; <strong><a href="https://astro.build/blog/astro-640/">Astro 6.4 goes full Rust on Markdown</a></strong>: <strong>Astro 6.4</strong> joins the Rust rewrite club with S&#228;tteri, a new Markdown processor that cut over a minute off real-world build times. It&#8217;s opt-in for now via the new <code>markdown.processor</code> API, but the team has flagged it as the likely future default, migration cost being the remark/rehype plugin compatibility.</p></li><li><p>&#129302; <strong><a href="https://www.anthropic.com/news/claude-opus-4-8">Claude Opus 4.8 drops as an incremental but meaningful upgrade</a></strong>: Better benchmark scores, sharper agentic judgment, and notably improved honesty (4&#215; less likely to let code flaws slip by unremarked). Pricing stays the same. Also shipping alongside it: effort controls on claude.ai, and a &#8220;dynamic workflows&#8221; feature in Claude Code that can spin up hundreds of parallel subagents for codebase-scale tasks.</p></li><li><p>&#127760; <strong><a href="https://web.dev/blog/baseline-digest-apr-2026">Web platform catches up on quality-of-life</a></strong>: <strong>April&#8217;s Baseline digest</strong> brought some solid platform wins: <code>contrast-color()</code> auto-picks readable text against any background, <code>Math.sumPrecise()</code> fixes floating-point drift in array sums, the <code>&lt;search&gt;</code> element now hands you an ARIA landmark for free, and ARIA attribute reflection means cleaner <code>element.ariaExpanded</code> syntax over <code>setAttribute</code>.</p></li></ul><h1 style="text-align: center;"><strong>Beyond the Headlines</strong></h1><ul><li><p><strong>&#9889; <a href="https://performance.dev/how-is-linear-so-fast-a-technical-breakdown">How is Linear so fast? A technical breakdown</a></strong>: Linear has become the benchmark for fast, responsive web applications, and this deep dive explores the engineering decisions behind that experience. From frontend architecture to rendering strategies and performance optimizations, the article breaks down the techniques that help the product feel almost instantaneous. The broader lesson is that performance is rarely the result of a single breakthrough. It comes from dozens of deliberate decisions across the stack, all working together to reduce friction and keep users in flow.</p></li><li><p><strong>&#129513; <a href="https://aurorascharff.no/posts/component-architecture-for-react-server-components/">Designing component architecture for React Server Components</a></strong>: React Server Components change more than just where code runs. They also influence how applications are structured and how responsibilities are divided between components. This article explores architectural patterns for organizing components in an RSC-based application and avoiding common pitfalls. As more frameworks embrace server-first rendering, understanding these patterns is becoming increasingly important. The challenge is no longer just building components, but deciding which ones belong on the server and which ones truly need to run on the client.</p></li><li><p><strong>&#128196; <a href="https://developer-api.foxit.com/developer-blogs/use-cases-workflow-examples/automated-document-pipelines/foxit-mcp-server-ai-pdf-tools/">Bringing AI workflows to PDF-heavy applications</a></strong>: As AI agents become more capable, one challenge remains consistent: documents. This article explores how Foxit&#8217;s MCP Server connects AI systems with PDF workflows, enabling tasks such as document analysis, extraction, and processing without requiring developers to build custom integrations from scratch. The bigger trend is the rise of infrastructure that helps AI agents interact with existing business systems. Rather than generating text in isolation, agents are increasingly being equipped to work with the documents and workflows that power day-to-day operations.</p></li><li><p><strong>&#128640; <a href="https://javascript.plainenglish.io/migrating-express-to-next-js-using-ai-agents-antigravity-f48b4c206a8e">Migrating from Express to Next.js with AI agents</a></strong><a href="https://javascript.plainenglish.io/migrating-express-to-next-js-using-ai-agents-antigravity-f48b4c206a8e">:</a> This case study explores using AI agents to help migrate an application from Express to Next.js. Rather than focusing solely on code generation, it examines how agents can assist with larger engineering tasks such as understanding existing architecture, planning migrations, and implementing changes across a codebase. The interesting takeaway is that AI is increasingly being used as a collaborator on complex development projects. The challenge is no longer whether AI can write code, but how effectively it can help developers navigate and transform existing systems.</p></li><li><p><strong>&#128506;&#65039; <a href="https://cassidoo.co/post/clustering-tiles/">What clustering map tiles can teach us about problem solving</a></strong>: In this post, Cassidy Williams walks through the challenge of clustering map tiles and the thought process behind solving it. Rather than focusing solely on the final solution, the article highlights the experimentation, trade-offs, and iterative thinking that go into tackling a seemingly simple problem. It&#8217;s a good reminder that software engineering is often less about finding the perfect algorithm and more about breaking complex problems into manageable pieces and refining solutions along the way.</p></li></ul><h1 style="text-align: center;"><strong>The Developer Toolbox</strong></h1><ul><li><p><strong>&#128293; <a href="https://flueframework.com/">Build reactive web apps without a framework runtime</a></strong>: Modern frontend frameworks often trade simplicity for abstractions. <strong>Flue</strong> takes a different approach, offering a reactive UI framework that focuses on minimal overhead, direct DOM updates, and a lightweight development experience. The project aims to deliver fine-grained reactivity without the complexity or runtime costs typically associated with larger frameworks. If you&#8217;re interested in exploring alternative approaches to building fast, reactive web applications, Flue is worth a look.</p></li><li><p><strong>&#9000;&#65039; <a href="https://jamiebuilds.github.io/tinykeys/">Handle keyboard shortcuts with minimal overhead</a></strong>: Keyboard shortcuts can quickly become messy as applications grow. <strong>Tinykeys</strong> is a lightweight JavaScript library that makes it easy to define and manage keyboard shortcuts with a simple, intuitive API. At under 1 KB, it supports complex key combinations and sequences without adding unnecessary weight to your application. If you&#8217;re building power-user features, command palettes, or productivity-focused interfaces, Tinykeys offers a clean way to handle keyboard interactions.</p></li></ul><p><em>That&#8217;s all for this week. Have any ideas you want to see in the next article? Hit Reply!</em></p><p>Cheers!</p><p>Editor-in-chief,</p><p>Kinnari Chohan</p><div><hr></div><p><strong>&#128075; <a href="https://landing.packtpub.com/sponsorship-landing-page/">Advertise with us</a></strong><br><strong> </strong>Interested in sponsoring this newsletter and reaching a highly engaged audience of tech professionals? Simply reply to this email, and our team will get in touch with the next steps.</p>]]></content:encoded></item><item><title><![CDATA[The CSS-First Mindset Modern Frontends Need Again]]></title><description><![CDATA[For years, frontend development has carried a quiet assumption: when an interface needs to respond, animate, toggle, validate, or remember state, JavaScript should take the lead.]]></description><link>https://packtwebdevpro.substack.com/p/the-css-first-mindset-modern-frontends</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/the-css-first-mindset-modern-frontends</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Mon, 25 May 2026 14:03:19 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!KWnM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F127ad044-e3ad-4bfe-9f00-1abd397cd2f4_1448x1086.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>For years, frontend development has carried a quiet assumption: when an interface needs to respond, animate, toggle, validate, or remember state, JavaScript should take the lead. That instinct made sense for a long time. Browsers were inconsistent, CSS was limited, and many interaction patterns genuinely needed script-heavy solutions to feel polished.</p><p>That landscape has changed. Modern HTML and CSS now handle far more than layout and decoration. They can respond to form state, respect system preferences, manage disclosure patterns, animate page transitions, create motion paths, style modal backdrops, and support accessible behavior that developers previously had to rebuild from scratch. The question is no longer &#8220;Can JavaScript do this?&#8221; because, of course, it can. The better question is &#8220;Should JavaScript be responsible for this?&#8221;</p><p>A CSS-first mindset does not mean rejecting JavaScript. It means giving the browser a fair chance before adding another dependency, state handler, event listener, or UI library. It asks developers to start with semantic HTML, layer CSS for presentation and interaction, and reserve JavaScript for the work it is uniquely good at: data fetching, complex application logic, persistence, coordination across systems, and genuinely dynamic behavior.</p><p>That small shift can change the quality of a frontend codebase. Interfaces become lighter, easier to reason about, more resilient when something fails, and often more accessible by default. For intermediate developers, this is one of the most useful habits to build: not writing less code for the sake of minimalism, but choosing the browser-native path when it gives users a better result.</p><p>Before we dig deeper into this, here&#8217;s a TL;DR you need:</p><ul><li><p>&#129408; <em><strong><a href="https://github.com/oven-sh/bun/pull/30412">Bun&#8217;s massive Rust rewrite reignites the JavaScript tooling conversation</a></strong></em></p></li><li><p>&#128274; <em><strong><a href="https://www.youtube.com/watch?v=gwTQLZSIlsU">TanStack&#8217;s supply chain compromise shows how fragile npm security still is</a></strong></em></p></li><li><p>&#127760; <em><strong><a href="https://developer.chrome.com/blog/install-element-ot">Chrome and Edge explore a native &lt;install&gt; element for PWAs</a></strong></em></p></li><li><p>&#128274; <em><strong><a href="https://socket.dev/blog/antv-packages-compromised">Shai Hulud returns with another package supply chain hit</a></strong></em></p></li><li><p>&#127909; <em><strong><a href="https://www.youtube.com/watch?v=6moPS3AAbe4">TanStack Start enters the framework race with a different philosophy</a></strong></em></p></li><li><p>&#129718; <em><strong><a href="https://github.com/addyosmani/critical">Critical 8.0 brings CSS performance back to first paint</a></strong></em></p></li></ul><h1><strong>The cost of reaching for JavaScript too early</strong></h1><p>JavaScript is powerful, but power has a cost. Every script has to be downloaded, parsed, compiled, and executed. Every custom interaction adds more behavior to maintain. Every dependency introduces another layer of updates, bundle impact, and possible failure. On a fast machine and a strong connection, those costs may feel invisible. On a slower device, a busy network, or a page already carrying analytics, ads, and third-party widgets, they become much easier to feel.</p><p>The issue is not that JavaScript is bad. The issue is that many teams use it as a default even when the browser already has the behavior built in. A simple accordion becomes a component with state. A modal becomes a focus-management exercise. A navigation highlight becomes a DOM query. A theme switcher becomes a script-first feature before CSS has been allowed to handle the visual logic.</p><div class="callout-block" data-callout="true"><p>This matters because users experience the final result, not the elegance of our tooling. A lighter interface often loads faster, responds sooner, and fails more gracefully. It also tends to be easier for the next developer to understand. When structure lives in HTML, behavior comes from native elements, and styling expresses state through CSS, the codebase has fewer hidden moving parts.</p></div><h1><strong>CSS is becoming contextual, not just decorative</strong></h1><p>One of the most important changes in modern CSS is that it can respond to context. The :has() selector is a good example. For a long time, CSS could style children based on parents, descendants based on ancestors, and siblings in limited directions, but it struggled with parent-level conditions. Developers often added JavaScript just to say, &#8220;Style this container differently when something inside it is checked, active, hovered, or present.&#8221;</p><p>That kind of logic now fits naturally into CSS. A fieldset can react when a checkbox inside it is selected. A navigation item can show an indicator only when it contains a submenu. A card list can blur non-hovered cards when one card is active. A layout can switch when a form control changes state. These are visual responses to visual conditions, which makes CSS a better home for them than JavaScript.</p><p>The real takeaway is not simply that :has() is useful. It is that CSS is moving closer to how designers and developers think about interfaces. Components rarely exist in isolation. Their styling depends on state, nearby elements, available space, user preferences, and interaction context. The more CSS can express those relationships directly, the less we need to create artificial classes or scripts just to bridge the gap.</p><div class="callout-block" data-callout="true"><p>There is still a performance and maintainability angle to consider. Broad relational selectors can ask the browser to do more work than necessary, especially on large pages. A focused selector that checks for a nearby .active element is easier to maintain than one that searches through a deeply nested structure. Like any powerful feature, :has() rewards restraint.</p></div><h1><strong>Native elements carry behavior we often forget to value</strong></h1><p>A CSS-first approach becomes even stronger when paired with semantic HTML. Elements such as &lt;dialog&gt;, &lt;details&gt;, and &lt;summary&gt; are not just markup conveniences. They carry interaction behavior that many teams have spent years recreating.</p><p>Take modals. A custom modal usually needs background blocking, focus handling, Escape-key behavior, ARIA wiring, open and close logic, and backdrop styling. The native &lt;dialog&gt; element handles much of this through the browser. With showModal(), the page gets modal behavior without a large custom system. CSS can then style the dialog and its ::backdrop, while a small amount of JavaScript handles the moment it opens.</p><p>Accordions tell a similar story. The &lt;details&gt; and &lt;summary&gt; elements provide disclosure behavior without building state from scratch. They work with keyboard interaction, keep content structured, and remain understandable even when CSS enhancements are unavailable. When multiple details elements share a name, they can behave like a grouped accordion where opening one closes another. That is a meaningful reduction in custom logic.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!KWnM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F127ad044-e3ad-4bfe-9f00-1abd397cd2f4_1448x1086.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!KWnM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F127ad044-e3ad-4bfe-9f00-1abd397cd2f4_1448x1086.png 424w, https://substackcdn.com/image/fetch/$s_!KWnM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F127ad044-e3ad-4bfe-9f00-1abd397cd2f4_1448x1086.png 848w, https://substackcdn.com/image/fetch/$s_!KWnM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F127ad044-e3ad-4bfe-9f00-1abd397cd2f4_1448x1086.png 1272w, https://substackcdn.com/image/fetch/$s_!KWnM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F127ad044-e3ad-4bfe-9f00-1abd397cd2f4_1448x1086.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!KWnM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F127ad044-e3ad-4bfe-9f00-1abd397cd2f4_1448x1086.png" width="1448" height="1086" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/127ad044-e3ad-4bfe-9f00-1abd397cd2f4_1448x1086.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1086,&quot;width&quot;:1448,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!KWnM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F127ad044-e3ad-4bfe-9f00-1abd397cd2f4_1448x1086.png 424w, https://substackcdn.com/image/fetch/$s_!KWnM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F127ad044-e3ad-4bfe-9f00-1abd397cd2f4_1448x1086.png 848w, https://substackcdn.com/image/fetch/$s_!KWnM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F127ad044-e3ad-4bfe-9f00-1abd397cd2f4_1448x1086.png 1272w, https://substackcdn.com/image/fetch/$s_!KWnM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F127ad044-e3ad-4bfe-9f00-1abd397cd2f4_1448x1086.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="callout-block" data-callout="true"><p>This is where developers can level up quickly. Instead of asking, &#8220;Which package should I install for this UI pattern?&#8221; ask, &#8220;Does HTML already have a primitive for this?&#8221; Native primitives may not cover every product requirement, but they often provide a stronger baseline than a custom implementation written under deadline pressure.</p></div><h1><strong>Accessibility improves when the browser keeps its job</strong></h1><p>Many accessibility problems come from replacing native behavior with custom behavior and then forgetting to rebuild all the pieces users rely on. A div that behaves like a button still needs keyboard support, focus styles, roles, states, and expected interaction patterns. A custom accordion still needs to communicate its expanded state. A custom modal still needs to manage focus without trapping users in awkward ways.</p><p>CSS-first and HTML-first thinking reduces that risk. Native controls already know a lot about input methods, assistive technologies, system preferences, and user expectations. A range input can be dragged, focused, and adjusted with the keyboard. A summary element can be opened without a custom click handler. A dialog can announce itself with the right labeling when structured properly.</p><p>This does not remove responsibility from developers. Accessibility still requires care. Motion should respect prefers-reduced-motion. Theme choices should preserve contrast. Generated content should not be the only place important information exists, because pseudo-elements are not always announced. A CSS-generated counter, for example, may need an accessible label or equivalent text in the markup.</p><div class="callout-block" data-callout="true"><p>The practical lesson is simple: let native behavior do as much as it reasonably can, then enhance it thoughtfully. Accessibility is not a polish step at the end. It is often a direct result of choosing the right primitive at the beginning.</p></div><h1><strong>Progressive enhancement is back in a practical way</strong></h1><p>Modern CSS features arrive at different speeds across browsers. That can make teams cautious, especially when they remember older eras of painful browser inconsistencies. The healthier approach is not to avoid new CSS entirely. It is to use progressive enhancement deliberately.</p><p>Some features are safe because unsupported browsers simply fall back to a usable experience. Smooth scrolling can fall back to normal anchor jumps. Accordion animations can fall back to instant open and close behavior. A masked comparison slider can still expose a native range input with a simpler presentation. View transitions can be ignored by unsupported browsers while navigation continues to work.</p><p>Feature queries such as @supports help developers layer enhancements only where browsers understand them. User preference queries such as prefers-color-scheme and prefers-reduced-motion let sites adapt to the person using them rather than forcing one visual experience on everyone. This is not just technical neatness. It is a more respectful way to build for a web that runs across different devices, settings, and constraints.</p><div class="callout-block" data-callout="true"><p>The best progressive enhancement does not make the baseline feel broken. It starts with functional HTML, improves the experience with widely supported CSS, and adds newer capabilities where they make the interface smoother or more expressive. The result feels modern without becoming fragile.</p></div><h1><strong>Motion needs purpose, not just possibility</strong></h1><p>CSS can now create polished motion without JavaScript timers or heavy libraries. Infinite logo sliders, animated borders, view transitions, motion paths, and scroll-driven effects can all be handled mostly or entirely through CSS. That is exciting, but motion should earn its place.</p><p>A partner logo strip that moves continuously may add energy, but it should pause on hover or focus so users can inspect it. Page transitions can make navigation feel smoother, but they should not slow users down or become disorienting. A glowing animated border may draw attention to a feature card, but the interface should still feel calm when motion is reduced.</p><p>This is where CSS gives developers a useful advantage. Animations can be expressed declaratively, paused with state selectors, and disabled through media queries. Rather than manually coordinating timers, listeners, and cleanup, the browser can manage the animation lifecycle. That usually leads to smoother performance and simpler code.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GKae!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88fd5b46-5e85-4664-9b7e-a8e1a0b50b23_1448x1086.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GKae!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88fd5b46-5e85-4664-9b7e-a8e1a0b50b23_1448x1086.png 424w, https://substackcdn.com/image/fetch/$s_!GKae!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88fd5b46-5e85-4664-9b7e-a8e1a0b50b23_1448x1086.png 848w, https://substackcdn.com/image/fetch/$s_!GKae!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88fd5b46-5e85-4664-9b7e-a8e1a0b50b23_1448x1086.png 1272w, https://substackcdn.com/image/fetch/$s_!GKae!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88fd5b46-5e85-4664-9b7e-a8e1a0b50b23_1448x1086.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GKae!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88fd5b46-5e85-4664-9b7e-a8e1a0b50b23_1448x1086.png" width="1448" height="1086" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/88fd5b46-5e85-4664-9b7e-a8e1a0b50b23_1448x1086.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1086,&quot;width&quot;:1448,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!GKae!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88fd5b46-5e85-4664-9b7e-a8e1a0b50b23_1448x1086.png 424w, https://substackcdn.com/image/fetch/$s_!GKae!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88fd5b46-5e85-4664-9b7e-a8e1a0b50b23_1448x1086.png 848w, https://substackcdn.com/image/fetch/$s_!GKae!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88fd5b46-5e85-4664-9b7e-a8e1a0b50b23_1448x1086.png 1272w, https://substackcdn.com/image/fetch/$s_!GKae!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88fd5b46-5e85-4664-9b7e-a8e1a0b50b23_1448x1086.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="callout-block" data-callout="true"><p>The deeper takeaway is that CSS motion works best as communication. It can show continuity, guide attention, reveal relationships, or make a state change feel less abrupt. Motion that exists only because it is possible tends to age badly. Motion that helps users understand what changed is much more likely to belong.</p></div><h1><strong>The future frontend stack may be smaller than we expected</strong></h1><p>The frontend ecosystem often moves by adding layers. More state management, more rendering strategies, more build tools, more component abstractions. Many of those tools solve real problems, especially in application-heavy environments. But the browser itself has also been moving forward, and sometimes our habits have not caught up.</p><p>A smaller stack does not mean a less capable interface. It can mean choosing CSS variables for theming before inventing a theme engine. It can mean using prefers-color-scheme before writing theme detection logic. It can mean using &lt;dialog&gt; before importing a modal package. It can mean using scroll-margin-top before writing scroll offset JavaScript. It can mean allowing CSS counters to number content instead of maintaining numbers by hand.</p><p>The strongest teams will not be the ones that avoid JavaScript. They will be the ones that know when not to spend it. JavaScript should still handle persistence for a saved theme choice, fetch fresh data, coordinate complex interactions, and power application logic. But it should not automatically inherit every small UI responsibility simply because it can.</p><div class="callout-block" data-callout="true"><p>A CSS-first mindset gives developers more options. It helps teams ship less code, lean on browser behavior, and build interfaces that survive better across conditions. Most importantly, it brings the craft of frontend development closer to the web&#8217;s original strength: resilient layers that work together rather than one layer trying to do everything.</p></div><h1><strong>Takeaways</strong></h1><p>Modern CSS is no longer just a styling layer. It can express state, context, user preferences, motion, and responsive interaction patterns that once required JavaScript. Intermediate developers should treat CSS and semantic HTML as active parts of interface architecture, not just the final presentation pass.</p><p>The best use of JavaScript is intentional. Reach for it when the interface needs data, persistence, complex logic, or behavior the browser cannot provide on its own. For many everyday UI patterns, native HTML and CSS now provide a lighter, more accessible, and more maintainable starting point.</p><p>Progressive enhancement is the safest way to adopt newer features. Build a solid baseline first, then layer modern selectors, animations, masks, transitions, and preference-aware behavior where support allows. Users get a functional experience everywhere, and a richer one in capable browsers.</p><p>The real mindset shift is simple: before adding script, pause and ask whether the browser already understands the job. More often than many developers expect, the answer is yes.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IGjc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0016f1b2-7b2b-42ee-b1b2-4abffea02dc0_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IGjc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0016f1b2-7b2b-42ee-b1b2-4abffea02dc0_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!IGjc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0016f1b2-7b2b-42ee-b1b2-4abffea02dc0_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!IGjc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0016f1b2-7b2b-42ee-b1b2-4abffea02dc0_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!IGjc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0016f1b2-7b2b-42ee-b1b2-4abffea02dc0_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IGjc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0016f1b2-7b2b-42ee-b1b2-4abffea02dc0_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0016f1b2-7b2b-42ee-b1b2-4abffea02dc0_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!IGjc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0016f1b2-7b2b-42ee-b1b2-4abffea02dc0_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!IGjc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0016f1b2-7b2b-42ee-b1b2-4abffea02dc0_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!IGjc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0016f1b2-7b2b-42ee-b1b2-4abffea02dc0_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!IGjc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0016f1b2-7b2b-42ee-b1b2-4abffea02dc0_1536x1024.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><h1 style="text-align: center;"><strong>This Week in the News</strong></h1><ul><li><p>&#129302; <strong><a href="https://github.com/google/ax">Google open-sources Ax for distributed AI agents</a></strong>: Google has open-sourced <strong>Ax</strong>, a distributed runtime designed for building and coordinating AI agents across systems. The project focuses on managing agent execution at scale, reflecting growing interest in infrastructure for multi-agent workflows rather than standalone AI interactions.It&#8217;s another sign that the AI ecosystem is shifting from individual prompts toward orchestrated agent-based systems.</p></li><li><p>&#129512;<strong> <a href="https://github.com/oven-sh/bun/pull/30412">Bun&#8217;s Rust rewrite finally lands</a></strong>: Bun&#8217;s long-discussed Rust rewrite has now been merged, which gives the runtime another big moment in the JavaScript tooling conversation. The interesting part is not only the rewrite itself, but <a href="https://news.ycombinator.com/item?id=48019226">the debate around how it was produced</a>. With AI-ported code under scrutiny, this becomes a useful reminder that speed still needs engineering taste, review discipline, and trust in the codebase. For developers, Bun remains one of the most exciting projects to watch, but this merge also shows <a href="https://news.ycombinator.com/item?id=48150900">how closely the community is now examining</a> the way modern tooling gets built.</p></li><li><p>&#127760; <strong><a href="https://developer.chrome.com/blog/install-element-ot">Browsers may soon get a trusted PWA install button</a></strong>: Chrome and Edge are exploring a new &lt;install&gt; HTML element that would let browsers render a trusted install button for PWAs. That might sound like a small interface detail, but it points to a bigger shift in how seriously browsers want to treat installable web apps. PWA adoption has always had a discoverability problem. A native, browser-controlled install element could make the experience feel clearer, safer, and more consistent for users, while giving developers a cleaner path to promote app installation without relying on custom prompts.</p></li><li><p>&#127909; <strong><a href="https://www.youtube.com/watch?v=gwTQLZSIlsU">Fireship explains how one PR hijacked the npm registry</a></strong>: The npm ecosystem had another uncomfortable security lesson, and Fireship&#8217;s breakdown captures why this matters for everyday developers. A single compromised or malicious pull request can ripple through the dependency graph faster than most teams can react. JavaScript&#8217;s strength has always been its massive open ecosystem, but that same scale makes supply chain security everyone&#8217;s problem.</p></li><li><p>&#128274; <strong><a href="https://socket.dev/blog/antv-packages-compromised">Shai Hulud returns with another package supply chain hit</a></strong>: Shai Hulud struck again this week, affecting hundreds of packages and adding another serious entry to the JavaScript supply chain security story. At the same time, <a href="https://socket.dev/blog/node-ipc-package-compromised">node-ipc was also infected with a credentials stealer</a>, which makes this feel less like an isolated scare and more like a pattern developers need to plan around. The practical question for teams is no longer whether package compromise can happen. It is how quickly they can detect, contain, rotate credentials, and recover when it does.</p></li></ul><h1 style="text-align: center;"><strong>Beyond the Headlines</strong></h1><ul><li><p><strong>&#128250; <a href="https://www.youtube.com/watch?v=6moPS3AAbe4">TanStack Start takes its shot at the framework conversation</a></strong>: Tanner Linsley&#8217;s conversation on TanStack Start is worth watching because it is a candid look at what it takes to compete in a space where Next.js already shapes many developers&#8217; expectations. TanStack has earned trust through focused, composable tools, and Start is trying to bring that same philosophy into full-stack app development. The bigger story is how much appetite still exists for frameworks that give developers more control without asking them to give up modern conventions.</p></li><li><p>&#129513; <strong><a href="https://denodell.com/blog/browsers-treat-big-sites-differently">Browser engines quietly patch the web for popular sites</a></strong>: Some browsers ship built-in <a href="https://searchfox.org/firefox-main/source/browser/extensions/webcompat/data/interventions">tweaks for specific popular sites</a> when those sites do not render correctly by default. Firefox and Safari both do this, which says a lot about the messy reality behind the &#8220;web standards&#8221; ideal. Developers often talk about browser compatibility as though it is only about specs, but the web also runs on pragmatism. When a major site breaks, browser teams sometimes bend a little to preserve the user experience. It is a fascinating glimpse into the invisible maintenance work that keeps the modern web usable.</p></li><li><p>&#129504; <strong><a href="https://justsitandgrin.im/posts/native-all-the-way-until-you-need-text/">The limits of native code deserve a closer look</a></strong>: Artem Loenko&#8217;s piece on native code lands at a useful time, especially as more web developers think about performance through the lens of Rust, WebAssembly, and lower-level tooling. Native code can be powerful, but it is not a magic escape hatch. Complexity, portability, safety, developer experience, and maintenance still matter. The best engineering choices usually come from knowing where native code helps, where it complicates things, and where higher-level tools already do the job well enough.</p></li><li><p>&#127793; <strong><a href="https://nesbitt.io/2026/05/19/dumb-ways-for-an-open-source-project-to-die.html">Open source projects can die in surprisingly ordinary ways:</a></strong><a href="https://nesbitt.io/2026/05/19/dumb-ways-for-an-open-source-project-to-die.html">:</a> This piece is a sharp reminder that open source projects do not always fail because of dramatic technical problems. Sometimes they fade because maintainers burn out, governance is unclear, onboarding is painful, or the project quietly stops feeling worth the effort. For developers who depend on open source every day, it is worth reading with empathy. Healthy projects need more than stars, downloads, and GitHub activity. They need people, process, trust, and a path for new contributors to become part of the work.</p></li><li><p>&#129516; <strong><a href="https://joyeecheung.github.io/blog/2026/05/18/how-nodejs-and-v8-keep-each-other-working/">How Node.js and V8 keep each other working</a></strong>: Joyee Cheung&#8217;s deep dive into Node.js and V8 is a great read for anyone who wants to understand the machinery behind the runtime we use so casually. Node&#8217;s relationship with V8 is not a simple dependency story. It is an ongoing coordination effort across APIs, internals, performance work, compatibility, and release timing. This is the kind of behind-the-scenes engineering that rarely gets the spotlight, but it directly shapes what JavaScript developers can build and how reliably their apps run.</p></li></ul><h1 style="text-align: center;"><strong>Practical AI for Working Developers</strong></h1><p>AI is moving fast, and for a lot of developers, keeping up still feels like learning through trial and error.</p><p><strong><a href="https://links.uk.defend.egress.com/Warning?crId=6a01e2d25805d0ca04bfae9f&amp;Domain=packt.com&amp;Threat=eNpzrShJLcpLzAEADmkDRA%3D%3D&amp;Lang=en&amp;Base64Url=eNoFwt0OgiAYANAnQn6ECW3NO0vbavMi8hLwY2oTm9BSn76dM6T0iSeM49fGZNw7c8uMV-jHFVzCROXSCMKQyLlH3FpASjGJnOGeUiHAFX05nWFvaD0t4_3SDEZLVgeSyaNrKxdHg8IMAnzsKs2fk75u4WH35nfo163YilYG8gcadCrY&amp;@OriginalLink=substack.com">BuildWithAI</a></strong><a href="https://links.uk.defend.egress.com/Warning?crId=6a01e2d25805d0ca04bfae9f&amp;Domain=packt.com&amp;Threat=eNpzrShJLcpLzAEADmkDRA%3D%3D&amp;Lang=en&amp;Base64Url=eNoFwt0OgiAYANAnQn6ECW3NO0vbavMi8hLwY2oTm9BSn76dM6T0iSeM49fGZNw7c8uMV-jHFVzCROXSCMKQyLlH3FpASjGJnOGeUiHAFX05nWFvaD0t4_3SDEZLVgeSyaNrKxdHg8IMAnzsKs2fk75u4WH35nfo163YilYG8gcadCrY&amp;@OriginalLink=substack.com"> </a>is Packt&#8217;s newsletter for engineers who want to move beyond AI headlines and start using it in real projects.</p><p>Backed by Packt&#8217;s 7,000+ tech books, courses, and expert resources across 1,000+ technologies, each issue brings you practical workflows, carefully chosen resources, and implementation guidance you can actually apply. Subscribe <strong><a href="https://links.uk.defend.egress.com/Warning?crId=6a01e2d25805d0ca04bfae9f&amp;Domain=packt.com&amp;Threat=eNpzrShJLcpLzAEADmkDRA%3D%3D&amp;Lang=en&amp;Base64Url=eNoFwt0OgiAYANAnQn6ECW3NO0vbavMi8hLwY2oTm9BSn76dM6T0iSeM49fGZNw7c8uMV-jHFVzCROXSCMKQyLlH3FpASjGJnOGeUiHAFX05nWFvaD0t4_3SDEZLVgeSyaNrKxdHg8IMAnzsKs2fk75u4WH35nfo163YilYG8gcadCrY&amp;@OriginalLink=substack.com">here</a></strong>.</p><h1 style="text-align: center;"><strong>The Developer Toolbox</strong></h1><ul><li><p>&#9889; <strong><a href="https://github.com/addyosmani/critical">Critical 8.0</a></strong>: Addy Osmani&#8217;s Critical 8.0 helps extract and inline above-the-fold CSS into HTML, which makes it useful for anyone still paying attention to real-world page speed. Performance work often gets buried under bigger framework conversations, but rendering fast still matters. Critical is a reminder that some of the highest-impact optimizations are practical, focused, and close to the browser&#8217;s first paint. For teams working on content-heavy sites, landing pages, or performance-sensitive web apps, this is a tool worth revisiting.</p></li><li><p>&#128467;&#65039; <strong><a href="https://svar.dev/blog/svar-calendar-for-react-svelte-vue/">SVAR Calendar brings a flexible calendar component across frameworks</a></strong>: SVAR Calendar offers a calendar component for React, Svelte, and Vue, with an MIT-licensed core and a commercial version for extended use cases. Calendar UI is one of those deceptively hard pieces of product development. It looks familiar until you need recurring events, custom views, localization, styling, and framework compatibility. SVAR&#8217;s cross-framework approach makes it interesting for teams that want a polished calendar foundation without building every interaction from scratch. The <a href="https://svar.dev/demos/calendar/">live demo</a> is worth a quick look.</p></li></ul>]]></content:encoded></item><item><title><![CDATA[WebDevPro #140: The Hidden Complexity Behind "Simple" Three.js Scenes ]]></title><description><![CDATA[Three.js projects often begin with a deceptively simple moment.]]></description><link>https://packtwebdevpro.substack.com/p/webdevpro-140-the-hidden-complexity</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/webdevpro-140-the-hidden-complexity</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Mon, 18 May 2026 14:03:32 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!-Epb!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c609e43-4006-496a-9adf-84620ff6b584_500x500.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Three.js projects often begin with a deceptively simple moment.</p><p>A cube appears on screen. A light illuminates the scene. The camera moves smoothly. An animation loop runs continuously.</p><p>At that stage, the experience feels manageable. The structure seems straightforward: create a scene, add geometry, configure lighting, and render continuously.</p><p>The early feedback loop is rewarding because visible progress happens quickly. A functioning 3D scene can come together in relatively little code, which creates the impression that the difficult part has already been solved.</p><p>But complexity in Three.js rarely appears immediately.</p><p>It emerges gradually through interaction between systems: lighting affects material perception, camera positioning changes spatial readability, shadows introduce rendering overhead, responsiveness alters composition, animation timing affects scene coherence, and asset complexity impacts performance.</p><p>The difficult part is not rendering the first object.</p><p>The difficult part is maintaining coherence as the scene evolves.</p><p>This is why many impressive Three.js demos struggle to become stable, scalable product experiences. The challenge is rarely the first rendered frame. The challenge is managing the growing interaction between rendering, animation, lighting, responsiveness, and scene organization over time.</p><p>Before we get into it, here&#8217;s a sneak peek of this week&#8217;s highlights:</p><ul><li><p><strong>&#128737;&#65039;</strong><em><strong><a href="https://vercel.com/changelog/next-js-may-2026-security-release">Next.js patches 13 vulnerabilities that teams should not leave to the firewall</a></strong></em></p></li><li><p><strong>&#127959;&#65039; </strong><em><strong><a href="https://x.ai/news/anthropic-compute-partnership">Anthropic&#8217;s Colossus deal puts AI infrastructure back in the spotlight</a></strong></em></p></li><li><p><strong>&#129302; </strong><em><strong><a href="https://agentfield.ai/github">AgentField turns multiple coding agents into one TypeScript workflow</a></strong></em></p></li><li><p><strong>&#129516; </strong><em><strong><a href="https://sylvie.fyi/posts/react2shell/">React2Shell shows how curiosity can become an ecosystem-level security story</a></strong></em></p></li><li><p><strong>&#9883;&#65039; </strong><em><strong><a href="https://www.youtube.com/watch?v=5QM7XjbqDug">React Server Components in five minutes</a></strong></em></p></li></ul><h3><strong>Small scenes feel deceptively manageable</strong></h3><p>Most Three.js projects begin with a minimal scene setup: a scene, a camera, a renderer, geometry, and a light source.</p><p>At this stage, the mental model feels clean and predictable. Each component appears isolated and understandable. The renderer draws frames. The camera controls perspective. Geometry defines visible structure. The scene acts as the container that brings everything together.</p><p>A basic setup often looks like this:</p><p><code>const scene = new THREE.Scene();<br><br>const camera = new THREE.PerspectiveCamera(<br>75,<br>window.innerWidth / window.innerHeight,<br>0.1,<br>1000<br>);<br><br>const renderer = new THREE.WebGLRenderer();<br><br>renderer.setSize(<br>window.innerWidth,<br>window.innerHeight<br>);<br><br>document.body.appendChild(<br>renderer.domElement<br>);</code></p><p>At this point, the scene feels conceptually simple because very few systems are interacting simultaneously. The objects are few, the camera is predictable, and the renderer has a clear job: draw what exists in the scene from the camera perspective.</p><p>Then geometry is added. The code still looks approachable because geometry, material, and mesh map neatly to what appears on screen:</p><p><code>const geometry = new THREE.BoxGeometry();<br><br>const material =<br>new THREE.MeshStandardMaterial({<br>color: 0x00ff00<br>});<br><br>const cube = new THREE.Mesh(<br>geometry,<br>material<br>);<br><br>scene.add(cube);</code></p><p>The result feels immediate and satisfying. Something visible exists on screen. The rendering pipeline works. The scene responds correctly.</p><p>This early success is useful, but it can also mislead. Developers often assume that scaling a Three.js project simply means adding more objects or more visual detail. In reality, complexity in 3D scenes rarely grows in a straight line. It compounds through interaction between systems.</p><p>That distinction becomes increasingly important as scenes evolve beyond isolated demos. The first object is usually easy. The ongoing challenge is keeping the scene predictable as more rendering decisions begin depending on one another.</p><h3><strong>Complexity appears through interaction, not object count</strong></h3><p>One of the biggest misconceptions in Three.js development is that complexity scales primarily through object count. Object count matters, but it is not the whole story.</p><p>In practice, complexity scales through interaction between systems. A single additional light source can change material appearance, shadow calculations, rendering cost, scene mood, and spatial readability. A camera adjustment can change composition, movement perception, interaction feel, and depth relationships. An animation update can change render timing, synchronization behavior, responsiveness, and motion continuity.</p><p>This interconnected behavior is what makes seemingly small scenes difficult to maintain. A change that looks isolated at code level may affect how the entire scene feels to the user.</p><p>A simplified dependency chain often looks like this:</p><p><code>Geometry<br>-&gt;<br>Material appearance<br>-&gt;<br>Lighting interaction<br>-&gt;<br>Shadow rendering<br>-&gt;<br>Performance impact<br>-&gt;<br>Perceived scene quality</code></p><p>The important detail is that changes rarely remain localized. A developer may adjust lighting to improve realism, only to discover that materials now appear overly reflective, shadows become visually noisy, scene contrast becomes inconsistent, or frame rate drops unexpectedly.</p><p>The original change was small. The resulting system impact is much larger.</p><p>This is one of the defining characteristics of Three.js applications: systems continuously influence one another. The difficult part is no longer understanding individual features in isolation. The difficult part is understanding how rendering systems behave collectively once the scene becomes more sophisticated.</p><p>That same coordination challenge is starting to shape how developers use AI tools in day-to-day engineering work. The value is not simply asking an assistant to generate code. It is learning how to structure implementation, inspect output, debug issues, and keep the workflow understandable as the project becomes more complex.</p><p>That is the focus of <em><strong><a href="https://www.eventbrite.co.uk/e/hands-on-claude-code-for-beginners-tickets-1989081541435?aff=webdev">Learn Claude Code by Building Live</a></strong></em>, a live hands-on workshop built around practical AI-assisted development workflows. You&#8217;ll see how developers are using Claude Code across coding, debugging, reviewing AI-generated output, managing implementation workflows, and shipping software faster with structured practices.</p><p>Register now with a <strong><a href="https://www.eventbrite.co.uk/e/hands-on-claude-code-for-beginners-tickets-1989081541435?aff=webdev">40% early bird discount using code WEB40</a></strong>.</p><h3><strong>Lighting changes everything</strong></h3><p>Lighting is one of the clearest examples of hidden scene complexity.</p><p>In early Three.js experiments, lighting often feels secondary. Developers focus primarily on geometry because visible objects create immediate visual progress. But lighting determines how the entire scene is perceived.</p><p>Even simple lighting adjustments dramatically alter realism, atmosphere, depth perception, visual hierarchy, and readability. A scene with the same geometry can feel flat, dramatic, realistic, or confusing depending on how light is positioned and balanced.</p><p>For example, adding a directional light initially appears straightforward:</p><p><code>const light =<br>new THREE.DirectionalLight(<br>0xffffff,<br>1<br>);<br><br>light.position.set(5, 10, 7.5);<br><br>scene.add(light);</code></p><p>At first glance, this looks simple. The light has a color, an intensity, and a position. It is added to the scene, and the object becomes easier to read.</p><p>But lighting configuration quickly expands into broader considerations: shadow softness, contrast balance, reflection behavior, intensity calibration, color temperature, and rendering overhead. The complexity becomes more visible once multiple lights interact together.</p><p>Adding ambient light may improve visibility while simultaneously flattening scene depth. Increasing directional light intensity may improve realism while creating harsh contrast in unintended areas. Enabling shadows may improve depth but introduce performance cost.</p><p>This is why lighting rarely behaves like an isolated feature. It becomes part of the overall visual architecture of the scene. As projects mature, developers spend less time asking whether the light works and more time asking whether the lighting supports the experience consistently across the entire scene.</p><h3><strong>Materials introduce hidden rendering complexity</strong></h3><p>Materials often appear straightforward early in development. A developer selects a material type, applies a color or texture, and the object renders correctly. At prototype stage, that feels sufficient.</p><p>But materials are deeply connected to lighting behavior, reflections, transparency, render ordering, texture consistency, and performance characteristics. Material choices determine not only how an object looks, but how that object responds to the rest of the scene.</p><p>A simple material configuration might look like this:</p><p><code>const material =<br>new THREE.MeshPhysicalMaterial({<br>color: 0xffffff,<br>metalness: 0.8,<br>roughness: 0.2<br>});</code></p><p>The complexity is not immediately visible because the material appears correct in isolation. But as scenes evolve, materials begin interacting with multiple light sources, different environment maps, transparency layers, post-processing effects, and varied asset types.</p><p>This creates a coordination problem rather than a simple rendering problem. One object may appear overly reflective under certain lighting conditions. Another may absorb too much light. Texture resolution differences may become visually distracting once assets appear together inside the same scene.</p><p>These are not isolated rendering problems. They are scene consistency problems.</p><p>This is why material systems often become harder to manage over time than geometry itself. Geometry defines structure. Materials define how that structure is visually interpreted, and that interpretation changes continuously depending on the rest of the rendering environment.</p><h3><strong>Animation coordination becomes difficult quickly</strong></h3><p>Animation is another area where hidden complexity emerges gradually.</p><p>A single rotating object feels simple because the animation loop is easy to understand. The frame updates, the object rotates, and the renderer draws the updated scene:</p><p><code>function animate() {<br>requestAnimationFrame(animate);<br><br>cube.rotation.x += 0.01;<br>cube.rotation.y += 0.01;<br><br>renderer.render(scene, camera);<br>}<br><br>animate();</code></p><p>At prototype stage, this loop appears manageable because very little else is competing for synchronization. There is one object, one simple state change, and one render call.</p><p>But animation systems rarely remain isolated. As scenes evolve, animation begins interacting with camera movement, user interaction, lighting updates, physics systems, UI overlays, and asynchronous asset loading. This creates synchronization challenges that are far more difficult than the initial animation setup itself.</p><p>A simplified render relationship often looks like this:</p><p><code>User interaction<br>-&gt;<br>Animation updates<br>-&gt;<br>Scene state changes<br>-&gt;<br>Renderer updates frame<br>-&gt;<br>Camera reflects new state</code></p><p>The difficult part is no longer making objects move. The difficult part is ensuring movement remains coherent across the entire scene.</p><p>Animations that feel smooth individually may conflict once multiple systems update simultaneously. Timing inconsistencies become more noticeable. Interaction latency becomes more visible. Camera movement can make object animation feel too fast or too slow. UI overlays can make scene motion feel visually noisy.</p><p>This is one of the reasons polished 3D applications feel dramatically different from simple demos. The challenge is not merely creating animation. The challenge is coordinating animation behavior across the entire rendering system.</p><h3><strong>Scene organization matters more over time</strong></h3><p>Small Three.js scenes tolerate loose organization. Objects can exist directly inside the scene hierarchy without creating immediate problems. Early prototypes often remain understandable even with minimal structure.</p><p>As projects grow, however, organization becomes increasingly important. Grouping related objects improves transformation management, animation coordination, visibility control, scene readability, and maintainability.</p><p>A simple grouping structure might look like this:</p><p><code>const group = new THREE.Group();<br><br>group.add(mesh1);<br>group.add(mesh2);<br><br>scene.add(group);</code></p><p>Initially, this seems like a small architectural choice. Over time, decisions like this become foundational.</p><p>Without deliberate structure, animation logic becomes fragmented, object relationships become unclear, scene traversal grows more complicated, and interaction systems become difficult to manage.</p><p>The complexity of Three.js scenes often comes less from rendering itself and more from maintaining clarity as systems expand. This is where product-level thinking begins mattering more than individual rendering techniques.</p><h3><strong>Performance problems are usually architectural</strong></h3><p>Performance discussions around Three.js often focus heavily on rendering power. It is easy to assume that performance issues are mainly about the GPU, object count, or whether the browser can draw the scene quickly enough.</p><p>But many performance problems emerge from scene architecture rather than raw rendering capability. Examples include unnecessary object updates, excessive shadow calculations, uncontrolled geometry complexity, redundant render work, and poorly coordinated animation systems.</p><p>These issues accumulate gradually. A scene may perform well initially and degrade slowly as additional systems are introduced. Because the degradation is incremental, the underlying architectural cause is often harder to identify.</p><p>This is why optimization in Three.js is rarely about one dramatic fix. It usually involves improving coordination between systems: reducing unnecessary updates, simplifying lighting interactions, organizing scene hierarchy more effectively, and minimizing expensive rendering calculations.</p><p>The difficult part is not merely making a scene render. The difficult part is maintaining predictable performance as scene complexity grows.</p><h3><strong>Real complexity emerges through accumulation</strong></h3><p>One of the most important characteristics of Three.js development is that complexity compounds incrementally.</p><p>Rarely does a project become difficult because of one major rendering problem. Instead, one additional light is added, another animation loop appears, another material system is introduced, another interaction layer becomes necessary, and another responsive adjustment is required.</p><p>Each decision appears manageable independently. Together, they create an interconnected rendering system that requires significantly more coordination than the original prototype suggested.</p><p>This is why simple demos often feel deceptively complete. The early version demonstrates rendering capability. The mature version requires architectural discipline.</p><h3><strong>The difficult part is maintaining coherence</strong></h3><p>As Three.js scenes evolve, developers increasingly spend time maintaining coherence across rendering behavior, material consistency, animation timing, interaction responsiveness, scene organization, and performance stability.</p><p>This is where the nature of development changes.</p><p>The challenge is no longer:</p><p><em>Can we render this object?</em></p><p>The challenge becomes:</p><p><em>Can we keep the entire scene predictable, performant, and visually coherent as the system grows?</em></p><p>That is a fundamentally different kind of problem.</p><p>It requires structure, restraint, coordination, iterative refinement, and long-term thinking. These are architectural concerns rather than rendering concerns.</p><h3><strong>Key takeaways</strong></h3><ul><li><p>Simple Three.js scenes become complex through interaction between systems, not just object count.</p></li><li><p>Lighting, materials, camera behavior, animation, and performance continuously influence one another.</p></li><li><p>Demos can appear complete before the underlying scene structure is ready for real application growth.</p></li><li><p>Performance issues often emerge from scene organization and repeated updates rather than rendering alone.</p></li><li><p>The long-term challenge is maintaining visual and structural coherence as the scene evolves.</p></li></ul><h3><strong>Conclusion</strong></h3><p>Three.js scenes often appear simple during the early stages of development. A few objects, lights, and animations can quickly create impressive visual output.</p><p>But the hidden complexity of 3D applications emerges through interaction between systems.</p><p>Lighting affects materials. Animations affect rendering behavior. Responsiveness changes composition. Scene hierarchy affects maintainability. Performance depends on coordination across all of them.</p><p>The difficult part is not rendering the first object.</p><p>The difficult part is maintaining coherence as rendering, interaction, lighting, animation, and performance begin influencing one another simultaneously.</p><p>That is where simple scenes stop behaving like demos and start behaving like real applications.</p><h1 style="text-align: center;"><strong>This Week in the News</strong></h1><ul><li><p>&#129366; <strong><a href="https://github.com/oven-sh/bun/pull/30412">Bun&#8217;s million-line leap from Zig to Rust</a></strong>: Bun just made one of the boldest runtime moves we&#8217;ve seen in a while: a 1 million line PR that ports its codebase from Zig to Rust, only days after the branch was described as &#8220;experimental.&#8221; The reason is practical enough. Bun&#8217;s team has been chasing memory leaks and unpredictable crashes, and Rust gives them stronger language-level guardrails for exactly those problems. Still, swapping the foundation of a project this fast is bound to make developers nervous.</p></li><li><p><strong>&#129512; <a href="https://github.com/TanStack/router/issues/7383">TanStack&#8217;s npm compromise shows why fresh installs need a safety buffer</a>: </strong>A malicious npm publish hit 42 @tanstack/* packages this week, with 84 compromised versions live for a short window before being caught. The incident was contained quickly, but it still exposed a real risk for teams running fresh installs in local or CI environments. The practical move is to add friction around brand-new package releases, using safeguards like npm&#8217;s min-release-age, pnpm&#8217;s minimumReleaseAge, and GitHub Actions checks with tools such as zizmor.</p></li><li><p><strong>&#128737;&#65039;<a href="https://vercel.com/changelog/next-js-may-2026-security-release">Next.js patches 13 vulnerabilities that teams should not leave to the firewall</a>: </strong>Next.js shipped a coordinated security release covering 13 vulnerabilities across denial of service, middleware and proxy bypass, SSRF, cache poisoning, and XSS. Several issues cannot be fully mitigated by cloud firewalls, so the recommendation is straightforward: update to 15.5.18 or 16.2.6. There is also a related React Server Functions denial-of-service issue fixed in React RSC packages 19.2.6.</p></li><li><p><strong>&#127959;&#65039; <a href="https://x.ai/news/anthropic-compute-partnership">Anthropic&#8217;s Colossus deal puts AI infrastructure back in the spotlight</a></strong>:<strong> </strong>Anthropic&#8217;s latest compute expansion shows how much frontier AI now depends on access to massive infrastructure. SpaceX and xAI are making Colossus 1 available to Anthropic, giving Claude more capacity as demand grows. The bigger signal is that model competition is no longer only about architecture or benchmarks. It is also about who can secure enough compute, power, and data center capacity to keep products reliable at scale.</p></li><li><p><strong>&#129302; <a href="https://agentfield.ai/github">AgentField turns multiple coding agents into one TypeScript workflow</a></strong>: AgentField is positioning itself as a TypeScript harness for composing Claude Code, Codex, Gemini, and other coding agents into repeatable workflows. The interesting shift is from prompting one assistant at a time to coordinating agents with recipes, constraints, and reusable patterns. For teams experimenting with agentic development, this points toward a more structured way to test what coding agents can actually do together.</p></li></ul><h1 style="text-align: center;"><strong>Beyond the Headlines</strong></h1><ul><li><p><strong>&#9878;&#65039; <a href="https://read.engineerscodex.com/p/tokenmaxxing-promomaxxing-and-misaligned">Tokenmaxxing asks whether AI is increasing progress or just output</a>: </strong>This piece pushes back on the idea that more AI-generated work automatically means better engineering. Faster coding can help teams explore more ideas, but it can also create more noise, more unfinished features, and more coordination overhead. The useful question is not &#8220;how much can we generate?&#8221; but &#8220;what is worth keeping?&#8221;</p></li><li><p><strong>&#129516; <a href="https://sylvie.fyi/posts/react2shell/">React2Shell shows how curiosity can become an ecosystem-level security story</a>: </strong>This write-up traces the story behind React2Shell, an unauthenticated RCE in React Server Components. The value is not only in the vulnerability itself, but in how the discovery unfolded: curiosity, protocol digging, and a fast-moving disclosure process. It is a useful read for anyone working near modern React infrastructure.</p></li><li><p><strong>&#128269; <a href="https://www.jefftk.com/p/ai-is-breaking-two-vulnerability-cultures">AI is putting pressure on old vulnerability disclosure norms</a>: </strong>Jeff Kaufman looks at how AI changes the balance between quiet security fixes and coordinated disclosure. When AI can scan commits and infer security impact faster, &#8220;silent&#8221; fixes become easier to spot, and long embargoes become harder to manage. The result is a security culture clash that maintainers may not be able to ignore.</p></li><li><p><strong>&#129513; <a href="https://jadjoubran.io/blog/web-platform-influenced-by-libraries">Library patterns keep shaping what the web platform becomes</a>: </strong>This piece looks at how library patterns have influenced the web platform over time. The takeaway is simple: when developers repeatedly solve the same problem in userland, it often points to a missing browser primitive. Today&#8217;s popular library workaround can become tomorrow&#8217;s platform feature.</p></li><li><p><strong>&#9883;&#65039; <a href="https://www.youtube.com/watch?v=5QM7XjbqDug">React Server Components in five minutes</a>: </strong>This short deep dive is a useful companion to the React2Shell discussion because it focuses on the underlying React Server Components model. For developers who want a quick refresher, it helps connect the security conversation back to the architecture: what runs on the server, what reaches the client, and why those boundaries matter so much in modern React apps.</p></li></ul><div class="callout-block" data-callout="true"><h1 style="text-align: center;"><strong>Practical AI for Working Developers</strong></h1><p>AI is moving fast, and for a lot of developers, keeping up still feels like learning through trial and error.</p><p><strong><a href="https://links.uk.defend.egress.com/Warning?crId=6a01e2d25805d0ca04bfae9f&amp;Domain=packt.com&amp;Threat=eNpzrShJLcpLzAEADmkDRA%3D%3D&amp;Lang=en&amp;Base64Url=eNoFwt0OgiAYANAnQn6ECW3NO0vbavMi8hLwY2oTm9BSn76dM6T0iSeM49fGZNw7c8uMV-jHFVzCROXSCMKQyLlH3FpASjGJnOGeUiHAFX05nWFvaD0t4_3SDEZLVgeSyaNrKxdHg8IMAnzsKs2fk75u4WH35nfo163YilYG8gcadCrY&amp;@OriginalLink=substack.com">BuildWithAI</a></strong><a href="https://links.uk.defend.egress.com/Warning?crId=6a01e2d25805d0ca04bfae9f&amp;Domain=packt.com&amp;Threat=eNpzrShJLcpLzAEADmkDRA%3D%3D&amp;Lang=en&amp;Base64Url=eNoFwt0OgiAYANAnQn6ECW3NO0vbavMi8hLwY2oTm9BSn76dM6T0iSeM49fGZNw7c8uMV-jHFVzCROXSCMKQyLlH3FpASjGJnOGeUiHAFX05nWFvaD0t4_3SDEZLVgeSyaNrKxdHg8IMAnzsKs2fk75u4WH35nfo163YilYG8gcadCrY&amp;@OriginalLink=substack.com"> </a>is Packt&#8217;s newsletter for engineers who want to move beyond AI headlines and start using it in real projects.</p><p>Backed by Packt&#8217;s 7,000+ tech books, courses, and expert resources across 1,000+ technologies, each issue brings you practical workflows, carefully chosen resources, and implementation guidance you can actually apply. Subscribe <strong><a href="https://links.uk.defend.egress.com/Warning?crId=6a01e2d25805d0ca04bfae9f&amp;Domain=packt.com&amp;Threat=eNpzrShJLcpLzAEADmkDRA%3D%3D&amp;Lang=en&amp;Base64Url=eNoFwt0OgiAYANAnQn6ECW3NO0vbavMi8hLwY2oTm9BSn76dM6T0iSeM49fGZNw7c8uMV-jHFVzCROXSCMKQyLlH3FpASjGJnOGeUiHAFX05nWFvaD0t4_3SDEZLVgeSyaNrKxdHg8IMAnzsKs2fk75u4WH35nfo163YilYG8gcadCrY&amp;@OriginalLink=substack.com">here</a></strong>.</p></div><h1 style="text-align: center;"><strong>Tool of the Week</strong></h1><p><strong>&#128000; <a href="https://ratty-term.org/">Ratty makes the terminal weird, visual, and fun again</a></strong></p><p>Ratty is a terminal emulator with inline 3D graphics and a spinning rat cursor. It is playful, strange, and clearly built with a sense of humor, but that is what makes it worth a look. Developer tools do not always need to be purely utilitarian. Sometimes the experiment itself is the point.</p><p><em>That&#8217;s all for this week. Have any ideas you want to see in the next article? Hit Reply!</em></p><p>Cheers!</p><p>Editor-in-chief,</p><p>Kinnari Chohan</p><div><hr></div><p><strong>&#128075; <a href="https://landing.packtpub.com/sponsorship-landing-page/">Advertise with us</a></strong><br><strong> </strong>Interested in sponsoring this newsletter and reaching a highly engaged audience of tech professionals? Simply reply to this email, and our team will get in touch with the next steps.</p>]]></content:encoded></item><item><title><![CDATA[WebDevPro #139: The Developer’s Edge in an AI-Assisted Workflow]]></title><description><![CDATA[Welcome to this week&#8217;s issue of WebDevPro!]]></description><link>https://packtwebdevpro.substack.com/p/webdevpro-139-the-developers-edge</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/webdevpro-139-the-developers-edge</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Mon, 11 May 2026 14:02:52 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!5ICF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b73072a-8e1e-4a89-bde6-f704f598bd4b_800x532.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to this week&#8217;s issue of WebDevPro! Today&#8217;s piece features insights from <strong><a href="https://www.linkedin.com/in/markjamesprice/">Mark Price</a></strong>, a Microsoft Certified Solutions Developer and former Microsoft Certified Trainer with more than 30 years of experience.</p><p>Mark is also a bestselling author of programming books across .NET, C#, Python, and modern web development,</p><p>Mark brings a practical, developer-first lens to building strong technical foundations. Today&#8217;s piece is drawn from his book <em><strong><a href="https://www.amazon.com/Web-Dev-Sidekick-foundations-hands-ebook/dp/B0GTTXZ9V6">Web Development with an AI Sidekick</a></strong></em>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5ICF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b73072a-8e1e-4a89-bde6-f704f598bd4b_800x532.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5ICF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b73072a-8e1e-4a89-bde6-f704f598bd4b_800x532.jpeg 424w, https://substackcdn.com/image/fetch/$s_!5ICF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b73072a-8e1e-4a89-bde6-f704f598bd4b_800x532.jpeg 848w, https://substackcdn.com/image/fetch/$s_!5ICF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b73072a-8e1e-4a89-bde6-f704f598bd4b_800x532.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!5ICF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b73072a-8e1e-4a89-bde6-f704f598bd4b_800x532.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5ICF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b73072a-8e1e-4a89-bde6-f704f598bd4b_800x532.jpeg" width="442" height="293.93" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0b73072a-8e1e-4a89-bde6-f704f598bd4b_800x532.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:532,&quot;width&quot;:800,&quot;resizeWidth&quot;:442,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!5ICF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b73072a-8e1e-4a89-bde6-f704f598bd4b_800x532.jpeg 424w, https://substackcdn.com/image/fetch/$s_!5ICF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b73072a-8e1e-4a89-bde6-f704f598bd4b_800x532.jpeg 848w, https://substackcdn.com/image/fetch/$s_!5ICF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b73072a-8e1e-4a89-bde6-f704f598bd4b_800x532.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!5ICF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b73072a-8e1e-4a89-bde6-f704f598bd4b_800x532.jpeg 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>AI has changed the texture of web development work. A few years ago, most of us bounced between docs, Stack Overflow, GitHub issues, and half-finished notes in our own repos. Now, many developers open a chat window first. We ask for an explanation, a starter function, a refactor, a regex fix, or a quick way to debug a failing script. That shift is real, and it is already shaping how people learn and build.</p><p>Still, the real advantage does not come from generating code faster. It comes from using AI without giving away the thinking that makes you a stronger developer.</p><p>That matters most at the intermediate stage. Once you are past the basics, progress stops being about syntax recall alone. The actual challenge is understanding behavior, data flow, failure modes, and the trade-offs that sit behind everyday implementation choices. AI can support that process beautifully. It can also make it easier to skip it.</p><p>The difference comes down to one thing: your mental model.</p><p>Before we get into it, here&#8217;s a sneak peek of this week&#8217;s highlights:</p><ul><li><p>&#128640; <em><strong><a href="https://nodejs.org/en/blog/release/v26.0.0?">Node.js 26 is here with Temporal by default, V8 14.6, and new JavaScript capabilities.</a></strong></em></p></li><li><p>&#127744;<em><strong><a href="https://remix.run/blog/remix-3-beta-preview"> Remix 3 beta feels like a full reset, moving toward a web standards-first framework without React at the center.</a></strong></em></p></li><li><p>&#129517; <em><strong><a href="https://code.visualstudio.com/updates/v1_119">VS Code 1.119 sharpens agent workflows with smoother browser access, telemetry, and sandbox improvements.</a></strong></em></p></li><li><p>&#127760; <em><strong><a href="https://hacks.mozilla.org/2026/05/trustworthy-javascript-for-the-open-web/">Mozilla makes the case for trustworthy JavaScript and stronger guarantees around delivered browser code.</a></strong></em></p></li><li><p>&#9201;&#65039; <em><strong><a href="https://dev.to/lazarv/time-to-yield-20m8">Time to Yield revisits frontend responsiveness and why performance is also about keeping the interface alive.</a></strong></em></p></li><li><p>&#10024; <em><strong><a href="https://animejs.com/">Anime.js keeps web animation approachable with timelines, SVG animation, scroll effects, and draggable interactions.</a></strong></em></p></li></ul><h3><strong>JavaScript still lives or dies on behavior</strong></h3><p>In frontend work, JavaScript remains the place where user behavior becomes actual application behavior. A click updates a count. A form input changes local state. A toggle shows hidden content. A validation rule decides whether something can be submitted. These are ordinary interactions, but they expose the central challenge of frontend development: the browser is always reacting to changing state.</p><p>That is why JavaScript becomes harder long before it becomes &#8220;advanced.&#8221; The difficulty usually is not the syntax. It is the chain of cause and effect. One event triggers a function. That function updates a variable. The UI reads that value and renders it. Another function depends on that same value later. At that point, you are no longer writing isolated lines of code. You are managing behavior.</p><p><code>const button = document.querySelector(&#8217;#save&#8217;);<br>const status = document.querySelector(&#8217;#status&#8217;);<br><br>button.addEventListener(&#8217;click&#8217;, async () =&gt; {<br>status.textContent = &#8216;Saving...&#8217;;<br><br>try {<br>await saveDraft();<br>status.textContent = &#8216;Saved successfully&#8217;;<br>} catch (error) {<br>status.textContent = &#8216;Something went wrong&#8217;;<br>console.error(error);<br>}<br>});</code></p><p>This is a small example, but it shows the real shape of frontend work. The question is not just &#8220;does it run?&#8221; The question is &#8220;what should the user see while something is happening, and what should happen when it fails?&#8221;</p><p>That is also where AI can be genuinely useful. I find it most helpful when it is asked to explain behavior, not just produce output. If you ask it, &#8220;Why might this click handler fail silently?&#8221; or &#8220;What edge cases should I think about here?&#8221; you get much better value than you do from &#8220;write this feature for me.&#8221;</p><p>The browser still rewards developers who can reason clearly about state, events, and side effects. AI helps, but it does not remove that requirement.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WlRx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee25bf9-bb8e-4739-a38d-f3a581fdb97c_835x195.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WlRx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee25bf9-bb8e-4739-a38d-f3a581fdb97c_835x195.png 424w, https://substackcdn.com/image/fetch/$s_!WlRx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee25bf9-bb8e-4739-a38d-f3a581fdb97c_835x195.png 848w, https://substackcdn.com/image/fetch/$s_!WlRx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee25bf9-bb8e-4739-a38d-f3a581fdb97c_835x195.png 1272w, https://substackcdn.com/image/fetch/$s_!WlRx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee25bf9-bb8e-4739-a38d-f3a581fdb97c_835x195.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WlRx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee25bf9-bb8e-4739-a38d-f3a581fdb97c_835x195.png" width="835" height="195" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cee25bf9-bb8e-4739-a38d-f3a581fdb97c_835x195.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:195,&quot;width&quot;:835,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!WlRx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee25bf9-bb8e-4739-a38d-f3a581fdb97c_835x195.png 424w, https://substackcdn.com/image/fetch/$s_!WlRx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee25bf9-bb8e-4739-a38d-f3a581fdb97c_835x195.png 848w, https://substackcdn.com/image/fetch/$s_!WlRx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee25bf9-bb8e-4739-a38d-f3a581fdb97c_835x195.png 1272w, https://substackcdn.com/image/fetch/$s_!WlRx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcee25bf9-bb8e-4739-a38d-f3a581fdb97c_835x195.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><h3><strong>Debugging is still a first-class skill</strong></h3><p>One quiet risk with AI-generated code is that it can make clean-looking code feel trustworthy before it has earned that trust.</p><p>A function can look polished and still rely on DOM elements that do not exist. A promise can be written cleanly and still swallow an error. A generated solution can solve the visible symptom while leaving the original logic problem untouched. That is why debugging remains one of the most important skills in modern web work.</p><p>The console is still your friend. So are breakpoints, network inspection, and reading stack traces without panic. AI can help interpret an error, but the developer still needs to inspect the real runtime conditions.</p><p><code>const form = document.querySelector(&#8217;#signup-form&#8217;);<br><br>console.log(&#8217;Form found?&#8217;, !!form);<br><br>form?.addEventListener(&#8217;submit&#8217;, (event) =&gt; {<br>event.preventDefault();<br>console.log(&#8217;Form submitted&#8217;);<br>});</code></p><p>This snippet is simple, but it reflects a useful habit: check your assumptions in the environment where the code actually runs.</p><p>That habit matters more in AI-assisted workflows. If you paste an error into a chatbot before you inspect the actual state of the page, you risk outsourcing the wrong question. The better sequence is this: reproduce the issue, inspect the DOM or runtime values, form a hypothesis, then ask AI to help test or refine that hypothesis.</p><p>That turns AI into a debugging partner rather than a guess machine.</p><h3><strong>TypeScript makes fuzzy assumptions visible</strong></h3><p>JavaScript gives you freedom. TypeScript pushes back when that freedom becomes vague.</p><p>That is why TypeScript matters even for developers who already &#8220;know JavaScript.&#8221; Its biggest benefit is not prestige or complexity. It is visibility. It reveals where your assumptions are too loose.</p><p>If a user may not have a profile image, the code should say so. If a function returns either success data or an error object, the code should say so. If a property can only be one of three allowed strings, the code should say so.</p><p>That sounds obvious, but teams often carry these assumptions informally. AI-generated code tends to make that worse because it often fills in the blanks with something plausible rather than something verified.</p><p><code>type SurveyStatus = &#8216;draft&#8217; | &#8216;published&#8217; | &#8216;closed&#8217;;<br><br>interface Survey {<br>id: number;<br>title: string;<br>status: SurveyStatus;<br>responseCount?: number;<br>}<br><br>function getStatusLabel(survey: Survey): string {<br>if (survey.status === &#8216;draft&#8217;) return &#8216;Work in progress&#8217;;<br>if (survey.status === &#8216;published&#8217;) return &#8216;Live now&#8217;;<br>return &#8216;No longer accepting responses&#8217;;<br>}</code></p><p>This is not flashy code, but it is valuable code. It makes the shape of the data easier to understand at a glance. It also gives your editor a chance to protect you from sloppy assumptions.</p><p>This is where AI becomes much more effective, too. When you prompt with clear data shapes, expected states, and explicit constraints, the quality of the generated response improves immediately. Good prompts in development often look a lot like good system design. They define what is allowed, what is optional, and what should happen when something is missing.</p><p>Developers sometimes treat TypeScript as overhead because the application seems small. The problem is that applications rarely stay small in the ways that matter. They grow in decisions, edge cases, and invisible dependencies. TypeScript helps bring those decisions into the open.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ATpL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4b518bb-cc4d-4848-9ebc-52866c980b5b_1430x805.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ATpL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4b518bb-cc4d-4848-9ebc-52866c980b5b_1430x805.png 424w, https://substackcdn.com/image/fetch/$s_!ATpL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4b518bb-cc4d-4848-9ebc-52866c980b5b_1430x805.png 848w, https://substackcdn.com/image/fetch/$s_!ATpL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4b518bb-cc4d-4848-9ebc-52866c980b5b_1430x805.png 1272w, https://substackcdn.com/image/fetch/$s_!ATpL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4b518bb-cc4d-4848-9ebc-52866c980b5b_1430x805.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ATpL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4b518bb-cc4d-4848-9ebc-52866c980b5b_1430x805.png" width="1430" height="805" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b4b518bb-cc4d-4848-9ebc-52866c980b5b_1430x805.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:805,&quot;width&quot;:1430,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!ATpL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4b518bb-cc4d-4848-9ebc-52866c980b5b_1430x805.png 424w, https://substackcdn.com/image/fetch/$s_!ATpL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4b518bb-cc4d-4848-9ebc-52866c980b5b_1430x805.png 848w, https://substackcdn.com/image/fetch/$s_!ATpL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4b518bb-cc4d-4848-9ebc-52866c980b5b_1430x805.png 1272w, https://substackcdn.com/image/fetch/$s_!ATpL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4b518bb-cc4d-4848-9ebc-52866c980b5b_1430x805.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><h3><strong>Backend work rewards structure earlier than people expect</strong></h3><p>On the backend, the same pattern appears in a different form. It is easy to write a Python script that works once. It is much harder to build backend logic that stays understandable after a few rounds of changes, debugging, and feature growth.</p><p>That is why the backend conversation should not just be about language choice or framework speed. It should be about structure. Small functions, sensible modules, meaningful variable names, clear error handling, and isolated responsibilities all matter much earlier than most people expect.</p><p><code>def calculate_completion_rate(total_responses, completed_responses):<br>if total_responses == 0:<br>return 0<br><br>return round((completed_responses / total_responses) * 100, 2)</code></p><p>A tiny function like this is not interesting because it is clever. It is useful because it is readable, testable, and easy to reuse. That is often the better way to judge backend code quality. Not &#8220;How compact is it?&#8221; but &#8220;Can I understand it six weeks later?&#8221;</p><p>AI can help a lot here. It can suggest cleaner names, extract a helper function, explain a traceback, or show a better way to handle a repeated block of logic. Still, the best outcomes come when you already know what kind of structure you want.</p><p>If you ask AI to &#8220;write backend code for analytics,&#8221; you may get something that works. If you ask it to &#8220;separate data access, business logic, and formatting concerns,&#8221; you are much more likely to get something maintainable. That difference matters.</p><h3><strong>Good AI usage looks more like collaboration than delegation</strong></h3><p>There is a lot of talk about prompt engineering, but for most working developers, the real skill is much simpler: knowing how to ask better technical questions.</p><p>Strong AI-assisted development usually includes some version of the following habits:</p><ul><li><p>asking for an explanation before asking for a solution</p></li><li><p>requesting alternatives and trade-offs, not just one answer</p></li><li><p>giving the model the data shape, edge cases, and constraints up front</p></li><li><p>reviewing generated code line by line before accepting it</p></li><li><p>testing in the real environment, not just trusting a neat-looking response</p></li></ul><p>Those habits keep you in the driver&#8217;s seat.</p><p>Bad prompt:<br><em>&#8220;<strong>Write a form validation function.</strong>&#8220;</em><br><br>Better prompt:<br><em>&#8220;<strong>Write a TypeScript function that validates a survey form.</strong></em><br><em><strong>Fields: title (required, min 5 chars), email (optional, valid format if present),</strong></em><br><em><strong>questions (must contain at least 1 item).</strong></em><br><em><strong>Return an object with field-specific error messages.</strong>&#8220;</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!u4sI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a20bfc-dfa9-4349-ba3e-92bcc9cc6c15_1430x805.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!u4sI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a20bfc-dfa9-4349-ba3e-92bcc9cc6c15_1430x805.png 424w, https://substackcdn.com/image/fetch/$s_!u4sI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a20bfc-dfa9-4349-ba3e-92bcc9cc6c15_1430x805.png 848w, https://substackcdn.com/image/fetch/$s_!u4sI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a20bfc-dfa9-4349-ba3e-92bcc9cc6c15_1430x805.png 1272w, https://substackcdn.com/image/fetch/$s_!u4sI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a20bfc-dfa9-4349-ba3e-92bcc9cc6c15_1430x805.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!u4sI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a20bfc-dfa9-4349-ba3e-92bcc9cc6c15_1430x805.png" width="1430" height="805" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/94a20bfc-dfa9-4349-ba3e-92bcc9cc6c15_1430x805.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:805,&quot;width&quot;:1430,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!u4sI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a20bfc-dfa9-4349-ba3e-92bcc9cc6c15_1430x805.png 424w, https://substackcdn.com/image/fetch/$s_!u4sI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a20bfc-dfa9-4349-ba3e-92bcc9cc6c15_1430x805.png 848w, https://substackcdn.com/image/fetch/$s_!u4sI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a20bfc-dfa9-4349-ba3e-92bcc9cc6c15_1430x805.png 1272w, https://substackcdn.com/image/fetch/$s_!u4sI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a20bfc-dfa9-4349-ba3e-92bcc9cc6c15_1430x805.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><h3><strong>The real pattern is bigger than any one language</strong></h3><p>What I find most interesting is that the same deeper ideas keep showing up across the stack.</p><p>In JavaScript, you are reasoning about user interaction and state changes. In TypeScript, you are making assumptions explicit so those changes stay manageable. In Python, you are organizing logic so that behavior can scale without becoming confusing. Different syntax, same underlying discipline.</p><p>That is why AI works best for developers who are trying to strengthen their mental model, not bypass it.</p><p>A developer with a clear mental model asks better questions:</p><ul><li><p>What state is changing here?</p></li><li><p>What data shape does this function expect?</p></li><li><p>What happens when the input is missing or invalid?</p></li><li><p>Where should this responsibility live?</p></li><li><p>How should the system fail?</p></li><li><p>Is this solution easier to maintain than the last one?</p></li></ul><p>Those questions improve your code even before AI answers them. Then AI becomes useful in the right way. It helps you refine, test, explore, and debug. It stops being a code vending machine and starts acting more like a second pair of eyes.</p><h3><strong>Takeaways</strong></h3><p>AI is now part of the everyday web development toolkit, and that is not changing. The developers who benefit most will not be the ones who hand over every task blindly. They will be the ones who use AI to sharpen their understanding of the stack.</p><p>JavaScript still demands a clear grasp of browser behavior. TypeScript still rewards developers who make assumptions explicit. Python still works best when logic is structured early and cleanly. Across all three, the strongest habit is the same: treat generated output as something to interrogate, not something to trust by default.</p><p>That is the mindset worth building.</p><p>AI can speed up the path to a solution. Your mental model determines whether the solution actually holds up.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ovE3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa711c7b6-6e09-4e2c-8cee-eaaad973c844_1216x1500.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ovE3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa711c7b6-6e09-4e2c-8cee-eaaad973c844_1216x1500.png 424w, https://substackcdn.com/image/fetch/$s_!ovE3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa711c7b6-6e09-4e2c-8cee-eaaad973c844_1216x1500.png 848w, https://substackcdn.com/image/fetch/$s_!ovE3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa711c7b6-6e09-4e2c-8cee-eaaad973c844_1216x1500.png 1272w, https://substackcdn.com/image/fetch/$s_!ovE3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa711c7b6-6e09-4e2c-8cee-eaaad973c844_1216x1500.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ovE3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa711c7b6-6e09-4e2c-8cee-eaaad973c844_1216x1500.png" width="350" height="431.74342105263156" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a711c7b6-6e09-4e2c-8cee-eaaad973c844_1216x1500.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1500,&quot;width&quot;:1216,&quot;resizeWidth&quot;:350,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!ovE3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa711c7b6-6e09-4e2c-8cee-eaaad973c844_1216x1500.png 424w, https://substackcdn.com/image/fetch/$s_!ovE3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa711c7b6-6e09-4e2c-8cee-eaaad973c844_1216x1500.png 848w, https://substackcdn.com/image/fetch/$s_!ovE3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa711c7b6-6e09-4e2c-8cee-eaaad973c844_1216x1500.png 1272w, https://substackcdn.com/image/fetch/$s_!ovE3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa711c7b6-6e09-4e2c-8cee-eaaad973c844_1216x1500.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><em>If this way of thinking about AI-assisted development resonates with you, <strong>Web Dev with an AI Sidekick</strong> builds on the same idea in a more structured, practical way. You can pre-order the book on Amazon here: <strong><a href="https://www.amazon.com/Web-Dev-Sidekick-foundations-hands/dp/180611125X?utm_source=chatgpt.com">Web Dev with an AI Sidekick</a></strong></em></p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uqKv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F857b7ee0-012c-404b-8f9c-687434c2ada3_1880x940.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uqKv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F857b7ee0-012c-404b-8f9c-687434c2ada3_1880x940.png 424w, https://substackcdn.com/image/fetch/$s_!uqKv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F857b7ee0-012c-404b-8f9c-687434c2ada3_1880x940.png 848w, https://substackcdn.com/image/fetch/$s_!uqKv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F857b7ee0-012c-404b-8f9c-687434c2ada3_1880x940.png 1272w, https://substackcdn.com/image/fetch/$s_!uqKv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F857b7ee0-012c-404b-8f9c-687434c2ada3_1880x940.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uqKv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F857b7ee0-012c-404b-8f9c-687434c2ada3_1880x940.png" width="514" height="257" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/857b7ee0-012c-404b-8f9c-687434c2ada3_1880x940.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:728,&quot;width&quot;:1456,&quot;resizeWidth&quot;:514,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!uqKv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F857b7ee0-012c-404b-8f9c-687434c2ada3_1880x940.png 424w, https://substackcdn.com/image/fetch/$s_!uqKv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F857b7ee0-012c-404b-8f9c-687434c2ada3_1880x940.png 848w, https://substackcdn.com/image/fetch/$s_!uqKv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F857b7ee0-012c-404b-8f9c-687434c2ada3_1880x940.png 1272w, https://substackcdn.com/image/fetch/$s_!uqKv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F857b7ee0-012c-404b-8f9c-687434c2ada3_1880x940.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 style="text-align: center;"><strong>Join Anna J McDougall, Field CTO at HashiCorp / IBM, for a live workshop on how engineering careers are evolving in the AI era.</strong></p><p style="text-align: center;"><strong><a href="https://www.eventbrite.co.uk/e/career-paths-as-a-developer-in-the-ai-era-tickets-1987116539060?aff=newsletterinternal&amp;discount=innl40">&#128197; May 30 | Live Online Workshop</a></strong></p><p style="text-align: center;"><strong><a href="https://www.eventbrite.co.uk/e/career-paths-as-a-developer-in-the-ai-era-tickets-1987116539060?aff=newsletterinternal&amp;discount=innl40">Register Now</a></strong></p><div><hr></div><h1 style="text-align: center;"><strong>This Week in the News</strong></h1><ul><li><p><strong>&#128640; <a href="https://nodejs.org/en/blog/release/v26.0.0?utm_source=chatgpt.com">Node.js 26 lands as the new Current release</a>: </strong>Node.js 26 is here, with the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal">Temporal API</a> enabled by default, V8 14.6, and Undici 8. Developers also get new JavaScript capabilities such as <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/getOrInsert">Map.prototype.getOrInsert()</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/concat">Iterator.concat()</a>. This is the cutting-edge Current release until October, when Node.js 26 is expected to move to LTS. It is a good time to test compatibility, explore the runtime changes, and see what might affect production workflows later this year.</p></li><li><p><strong>&#127744; <a href="https://remix.run/blog/remix-3-beta-preview?utm_source=chatgpt.com">Remix 3 beta preview takes a sharper turn</a>: </strong>Remix has had a long journey: it was created by the team behind <a href="https://reactrouter.com/">React Router</a>, positioned as an <a href="https://nextjs.org/">alternative to Next.js</a>, acquired by <a href="https://www.shopify.com/">Shopify</a>, and later folded into React Router v7. Now Remix 3 is stepping out in a new direction: a full-stack, web standards-first framework with its own UI component model and no React at the center. It feels less like a version bump and more like a reset.</p></li><li><p><strong>&#129514;<a href="https://news.ycombinator.com/item?id=48016880&amp;utm_source=chatgpt.com">A Bun experiment turns into a bigger debate</a></strong>:<strong> </strong>Jarred Sumner added a <a href="https://github.com/oven-sh/bun">Zig to Rust porting guide</a> to the Bun repo, and Hacker News quickly turned it into a much larger conversation about Bun&#8217;s future. The speculation got intense enough that Jarred stepped in and said the whole thread was an overreaction. It is a small reminder of how closely developers watch fast-moving tools. Even an experiment can look like a strategy shift when the project has this much attention.</p></li><li><p>&#129517; <strong><a href="https://code.visualstudio.com/updates/v1_119?utm_source=chatgpt.com">VS Code 1.119 sharpens agent workflows</a></strong>: VS Code 1.119 focuses on smoother agent interactions, better observability, and fewer workflow interruptions. Agents can now request access to shared browser tabs, Copilot Chat sessions can emit <a href="https://opentelemetry.io/">OpenTelemetry</a> traces, and sandboxed agents get more practical network and temporary-file permissions. It is another step toward making AI coding agents feel less separate from the editor.</p></li></ul><h1 style="text-align: center;"><strong>Beyond the Headlines</strong></h1><ul><li><p><strong>&#128272; <a href="https://mobeigi.com/blog/security/security-through-obscurity-is-not-bad/?utm_source=chatgpt.com">Security through obscurity deserves a better conversation</a>: </strong>This piece challenges the usual dismissal of &#8220;security through obscurity.&#8221; The argument is not that obscurity should replace strong security, but that it can still be useful as one extra layer. It is a thoughtful read for anyone who has seen good security advice turn into rigid slogans.</p></li><li><p><strong>&#129391; <a href="https://wwj.dev/posts/i-am-worried-about-bun/">A developer worries about Bun&#8217;s future</a>: </strong>This post looks at Bun with both admiration and concern. The runtime is fast, ambitious, and widely loved, but its future now carries bigger questions around ownership, priorities, and long-term stewardship. The piece is a developer asking what happens when a tool people rely on becomes part of a much larger company story.</p></li><li><p><strong>&#127760; <a href="https://hacks.mozilla.org/2026/05/trustworthy-javascript-for-the-open-web/?utm_source=chatgpt.com">Mozilla makes the case for trustworthy JavaScript</a>: </strong>Mozilla explores how web apps can make their delivered JavaScript more trustworthy. The core concern is simple: users need a way to know that the code running in the browser is the code developers intended to ship. This matters most for high-trust apps, especially where privacy and encryption are involved. The open web needs stronger ways to make invisible tampering harder to hide.</p></li><li><p><strong>&#127909; <a href="https://www.youtube.com/watch?v=PX3QlADinIE">A useful watch for your developer queue</a>: </strong>I would keep this as a short watchlist item unless you want to share the title or main theme. Without that, the safest version is simple and curiosity-led. This video is worth saving for a slower watch, especially if you like technical talks that connect engineering decisions with the way developers actually build, debug, and maintain software.</p></li><li><p><strong>&#9201;&#65039;<a href="https://dev.to/lazarv/time-to-yield-20m8?utm_source=chatgpt.com">Time to Yield revisits frontend responsiveness</a>: </strong>This piece looks at yielding and responsiveness from a practical frontend angle. It is less about chasing benchmark wins and more about how JavaScript work affects the user&#8217;s experience. That framing is useful because performance is not only about speed. It is also about when work happens, how much room the browser gets, and whether the interface still feels alive under pressure.</p></li></ul><h1 style="text-align: center;"><strong>Practical AI for Working Developers</strong></h1><p>AI is moving fast, and for a lot of developers, keeping up still feels like learning through trial and error.</p><p><strong><a href="https://packtbuildwithai.substack.com/">BuildWithAI</a></strong><a href="https://packtbuildwithai.substack.com/"> </a>is Packt&#8217;s newsletter for engineers who want to move beyond AI headlines and start using it in real projects.</p><p>Backed by Packt&#8217;s 7,000+ tech books, courses, and expert resources across 1,000+ technologies, each issue brings you practical workflows, carefully chosen resources, and implementation guidance you can actually apply. Subscribe <a href="https://packtbuildwithai.substack.com/">here</a>.</p><h1 style="text-align: center;"><strong>Tool of the Week</strong></h1><p><strong><a href="https://animejs.com/">Anime.js keeps web animation approachable</a> &#10024;</strong></p><p>Anime.js gives developers a polished way to build expressive motion on the web, from timelines and SVG animation to scroll-triggered effects and draggable interactions. It is useful when animation needs to feel intentional rather than decorative. The API stays approachable, but there is enough depth for teams building more crafted, interactive interfaces.</p><p><strong><a href="https://crashcat.dev/examples/#example-shapes">Crashcat makes physics demos surprisingly fun</a> &#128049;</strong></p><p>Crashcat is a JavaScript 3D rigid body physics library for games, simulations, and interactive web experiences. It also has the kind of homepage you remember: a cat in a convertible driving through endless obstacles.</p><p>That playful first impression works. The examples make the library feel inviting before the technical details take over.</p><div><hr></div><p><em>That&#8217;s all for this week. Have any ideas you want to see in the next article? Hit Reply!</em></p><p>Cheers!</p><p>Editor-in-chief,</p><p>Kinnari Chohan</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://packtwebdevpro.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Web Development Newsletter by Packt! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[WebDevPro #138: The agentic coding loop: PRD → task planner → parallel agents]]></title><description><![CDATA[By Alexandre Zajac]]></description><link>https://packtwebdevpro.substack.com/p/webdevpro-138-the-agentic-coding</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/webdevpro-138-the-agentic-coding</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Mon, 04 May 2026 14:02:28 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!4zgw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3680c7a2-bb86-4af0-8c3e-5e588cc4dc14_500x620.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="callout-block" data-callout="true"><h1 style="text-align: center;"><strong><a href="https://www.vpdae.com/redirect/7au88233yznh73di5miqvjri992">Catch the latest HubSpot Developer Platform updates in Spring Spotlight</a></strong></h1><p>Spring Spotlight 2026 is live and we&#8217;ve rounded up the top updates for developers. See what&#8217;s new for the HubSpot Developer Platform!</p><p>Ship faster with AI coding tools like Cursor, Claude Code, and Codex. Build MCP-powered AI connectors, run serverless functions with support for UI extensions, and use date-based versioning to streamline roadmap planning.</p><p style="text-align: center;"><strong>Explore Now</strong></p></div><div><hr></div><p>Welcome to this week&#8217;s issue of WebDevPro!</p><p>Today&#8217;s piece comes from <strong><a href="https://go.hungryminds.dev/linkedin">Alexandre Zajac</a></strong>, an engineer from Prime Video who&#8217;s been thinking deeply about how AI coding workflows actually behave in the real world.</p><p>Alex doesn&#8217;t just experiment at the surface level; he digs into the friction points, the failure modes, and the patterns that emerge when you push agents beyond toy problems.</p><p>He built this <em><strong><a href="https://go.hungryminds.dev/agentic-loop-starter-kit">PDF starter kit</a></strong></em> to help you go 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_!4zgw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3680c7a2-bb86-4af0-8c3e-5e588cc4dc14_500x620.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4zgw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3680c7a2-bb86-4af0-8c3e-5e588cc4dc14_500x620.png 424w, https://substackcdn.com/image/fetch/$s_!4zgw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3680c7a2-bb86-4af0-8c3e-5e588cc4dc14_500x620.png 848w, https://substackcdn.com/image/fetch/$s_!4zgw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3680c7a2-bb86-4af0-8c3e-5e588cc4dc14_500x620.png 1272w, https://substackcdn.com/image/fetch/$s_!4zgw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3680c7a2-bb86-4af0-8c3e-5e588cc4dc14_500x620.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4zgw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3680c7a2-bb86-4af0-8c3e-5e588cc4dc14_500x620.png" width="216" height="267.84" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3680c7a2-bb86-4af0-8c3e-5e588cc4dc14_500x620.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:620,&quot;width&quot;:500,&quot;resizeWidth&quot;:216,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!4zgw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3680c7a2-bb86-4af0-8c3e-5e588cc4dc14_500x620.png 424w, https://substackcdn.com/image/fetch/$s_!4zgw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3680c7a2-bb86-4af0-8c3e-5e588cc4dc14_500x620.png 848w, https://substackcdn.com/image/fetch/$s_!4zgw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3680c7a2-bb86-4af0-8c3e-5e588cc4dc14_500x620.png 1272w, https://substackcdn.com/image/fetch/$s_!4zgw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3680c7a2-bb86-4af0-8c3e-5e588cc4dc14_500x620.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>In this article, he walks through a practical system for making agentic coding reliable, drawing from firsthand experience and real constraints. It&#8217;s thoughtful, grounded, and immediately useful if you&#8217;ve ever felt your AI sessions spiral after a few dozen turns.</p><p>Before we get into it, here&#8217;s a sneak peek of this week&#8217;s highlights:</p><ul><li><p><em>&#129504; <a href="https://poolside.ai/models">A new contender just entered the coding model race</a></em></p></li><li><p><em>&#9881;&#65039; <a href="https://cursor.com/blog/typescript-sdk">Cursor just turned its agents into an API</a></em></p></li><li><p><em>&#9883;&#65039; <a href="https://saschb2b.com/blog/react-compiler-year-in-review">React is still trying to automate performance</a></em></p></li><li><p><em>&#128994; <a href="https://github.com/nodejs/node/pull/62526">Node 26 hit a delay, but Temporal is still close</a></em></p></li><li><p><em>&#129504; <a href="https://openai.com/index/where-the-goblins-came-from">Where the goblins in ChatGPT actually came from</a></em></p></li><li><p><em>&#129513; <a href="https://openai.com/index/open-source-codex-orchestration-symphony/">Coding is shifting from prompts to orchestration</a></em></p><div><hr></div></li></ul><p>&#128075; Hi! It&#8217;s <a href="https://go.hungryminds.dev/linkedin">Alex</a>!</p><p>Let&#8217;s imagine this scene. You open a new chat. You describe the feature.<br>For twenty minutes, the AI is cooking.<br>Good code, too.</p><p>Around turn 30, it starts fixing a bug it introduced three turns ago.<br>It imports a module you deleted. It references a file path you renamed ten messages back.</p><p>You&#8217;re not building anymore. You&#8217;re managing.</p><p>Feeding corrections back in, watching the agent regenerate the same broken pattern with different variable names.</p><p>This is the death loop, and it&#8217;s not a prompt quality problem.<br>Session length is the variable that matters.</p><p>I created a simple system to ship simple changes with agents (almost) autonomously, and in this article, I want to show the why and how I built it.</p><h3><strong>Context erosion</strong></h3><p>The<a href="https://anthropic.com/engineering/claude-code-best-practices"> Anthropic Claude Code docs</a> say it directly: a single debugging session can generate tens of thousands of tokens, and when the context window fills up, Claude starts forgetting earlier instructions and making more mistakes.</p><p>A 10-turn session is fine.<br>A 50-turn session drifts.<br>At 80 turns, you&#8217;re spending more time correcting than building, and at that point, you might as well have written the code yourself.</p><p><a href="https://martinfowler.com/articles/exploring-gen-ai/13-role-of-developer-skills.html">Birgitta B&#246;ckeler</a>, writing in the Martin Fowler engineering series, said it after months of daily agentic coding: the longer a session gets, the more hit-and-miss it becomes, regardless of the rigor in prompting.</p><h3><strong>Assumption stacking</strong></h3><p>Agents make assumptions about your codebase.<br>Most are correct.</p><p>When one is wrong and goes unchallenged, the agent builds on it. Then you build on the agent&#8217;s code. Three levels in, the wrong assumption is load-bearing.</p><p>Documented example from the<a href="https://martinfowler.com/articles/exploring-gen-ai/13-role-of-developer-skills.html"> same Martin Fowler series</a>: an agent diagnosed a Docker build failure as an architecture mismatch and changed the Docker settings. The actual cause was node_modules built for the wrong platform. Classic error. Any developer who&#8217;s been burned by it once would catch it in 30 seconds. Without that catch, the agent would have spent hours deepening a wrong diagnosis into increasingly creative fixes.</p><p>Agents are <strong>confidently wrong</strong> with no built-in correction mechanism.</p><h3><strong>Filesystem collisions</strong></h3><p>Two agents, one working directory:</p><ul><li><p><strong>agent-1</strong>:</p></li></ul><p><code>git add . &amp;&amp; git commit -m &#8220;fix auth middleware&#8221;</code></p><ul><li><p><strong>agent-2:</strong></p></li></ul><p><code>git add . &amp;&amp; git commit -m &#8220;refactor API layer&#8221;</code></p><p># agent-2 just committed agent-1&#8217;s half-finished auth changes</p><p>Every agent sees every other agent&#8217;s uncommitted changes.<br>Files get overwritten mid-edit.<br>One agent&#8217;s npm install blows away another&#8217;s node_modules.</p><p>Commits become incoherent.</p><p>Open two Cursor tabs on the same repo and give it 20 minutes. Productive at first. Then a mess that takes longer to untangle than doing the work sequentially.</p><p>So how do we make this consistently okay?</p><h3><strong>Stage 1: The PRD</strong></h3><p>A PRD is not a 47-page corporate artifact. It&#8217;s a short document you write before opening your coding tool. Its job: prevent assumption stacking before the agent gets a chance to start.</p><p>I always use these for medium-to-large features.</p><p>It&#8217;s similar to the <a href="https://harper.blog/2025/02/16/my-llm-codegen-workflow-atm/">Harper Reed workflow</a> published in February 2025.</p><p>It got traction because it was concretely different from how most people worked at the time. His first move is a conversational spec session where an LLM asks him one question at a time until the idea is fully elaborated.</p><p>The prompt:</p><p>&#8220;<em><strong>Ask me one question at a time so we can develop a thorough,</strong></em></p><p><em><strong>step-by-step spec for this idea. Each question should build</strong></em></p><p><em><strong>on my previous answers, and our end goal is to have a detailed</strong></em></p><p><em><strong>specification I can hand off to a developer. Let&#8217;s do this</strong></em></p><p><em><strong>iteratively and dig into every relevant detail. Remember,</strong></em></p><p><em><strong>only one question at a time.&#8221;</strong></em></p><p><em><strong>Here&#8217;s the idea: [IDEA]</strong></em></p><p>When the questions run dry:</p><p><em><strong>&#8220;Now that we&#8217;ve wrapped up the brainstorming process, can you</strong></em></p><p><em><strong>compile our findings into a comprehensive, developer-ready</strong></em></p><p><em><strong>specification? Include all relevant requirements, architecture</strong></em></p><p><em><strong>choices, data handling details, error handling strategies,</strong></em></p><p><em><strong>and a testing plan so a developer can immediately begin</strong></em></p><p><em><strong>implementation.&#8221;</strong></em></p><p>Output goes to spec.md. The whole thing takes 15 minutes.</p><p>The<a href="https://www.runpane.com/blog/ai-native-development-workflow"> Doozy founders shipped a 300k-line Next.js monorepo</a> with 3 to 6 parallel agents at any given time. They do it differently. They built a /discussion command that runs before any code is written. Subagents explore the codebase and look up dependencies. The command produces no edits, only a written summary in .context/context.md. Other agents reference that file.</p><h4><strong>What goes in the spec</strong></h4><p><em><strong># spec.md</strong></em></p><p><em><strong>## Problem</strong></em></p><p><em><strong>What you&#8217;re building and why, in one sentence.</strong></em></p><p><em><strong>## Constraints</strong></em></p><p><em><strong>What the agent should NOT touch.</strong></em></p><p><em><strong>What patterns to follow.</strong></em></p><p><em><strong>## Files to read</strong></em></p><p><em><strong>src/auth/middleware.ts</strong></em></p><p><em><strong>src/routes/users.ts</strong></em></p><p><em><strong>prisma/schema.prisma</strong></em></p><p><em><strong>## Definition of done</strong></em></p><p><em><strong>npm run typecheck &amp;&amp; npm test passes with no new failures.</strong></em></p><p>150 to 300 words. The format matters less than writing it before you start prompting.</p><p>One test: if you can&#8217;t describe what the feature should <em>not</em> do, keep writing.</p><p>Where it lives: spec.md in the repo root, a context section in CLAUDE.md, or .context/context.md. Pick whatever your tool loads by default.</p><p>Watch out for CLAUDE.md files that balloon. The<a href="https://code.claude.com/docs/en/best-practices"> Claude Code docs</a> are explicit about this: bloated CLAUDE.md files cause Claude to ignore your actual instructions. Treat it like code. Prune it. If you added a rule and Claude&#8217;s behavior didn&#8217;t change, the rule is noise. Delete it.</p><h3><strong>Stage 2: The task planner</strong></h3><p>The task planner converts a spec into a sequenced list of bounded tasks.<a href="https://harper.blog/2025/02/16/my-llm-codegen-workflow-atm/"> Harper Reed</a> uses a reasoning model for this step, and I do too. Not for code, just for decomposition.</p><p>A possible prompt:</p><p><em><strong>Draft a detailed, step-by-step blueprint for building this project.</strong></em></p><p><em><strong>Then break it down into small, iterative chunks that build on each</strong></em></p><p><em><strong>other. Go another round to break it into small steps. Review and</strong></em></p><p><em><strong>make sure the steps are small enough to implement safely, but big</strong></em></p><p><em><strong>enough to move the project forward.</strong></em></p><p>Make sure each prompt builds on the previous prompts, and ends with wiring things together. There should be no hanging or orphaned code that isn&#8217;t integrated into a previous step.</p><p>[SPEC]</p><p>Output goes to prompt_plan.md. Then he asks for a todo.md checklist the execution agent can check off. That&#8217;s how state persists across sessions without re-reading the full conversation history.</p><p><a href="https://www.anthropic.com/research/building-effective-agents">Anthropic describes this as the orchestrator-workers pattern</a>: a central LLM breaks down tasks, delegates them to worker LLMs, and synthesizes results. The reasoning is that you can&#8217;t always predict the subtasks, especially in code, where the number of files and the nature of changes depend on the task.</p><h4><strong>What &#8220;agent-sized&#8221; means</strong></h4><p>A task is agent-sized if it fits in one context window, produces a green lint/typecheck, and has a binary done/not-done signal.</p><p>These will send your agent spiraling:</p><p><strong>&#10060;</strong><em><strong> &#8220;Refactor the authentication system&#8221;</strong></em></p><p><strong>&#10060;</strong><em><strong> &#8220;Add tests&#8221;</strong></em></p><p><strong>&#10060;</strong><em><strong> &#8220;Improve performance&#8221;</strong></em></p><p>These work:</p><p><strong>&#9989; </strong><em><strong>&#8220;Add a useAuth hook to src/hooks/auth.ts that wraps the</strong></em></p><p><em><strong>existing authService and exposes login, logout, and</strong></em></p><p><em><strong>isAuthenticated. Update src/components/LoginButton.tsx</strong></em></p><p><em><strong>to use it. Done when: npm run typecheck passes.&#8221;</strong></em></p><p><strong>&#9989;</strong> <em><strong>&#8220;Add a POST /api/users/:id/preferences endpoint to</strong></em></p><p><em><strong>src/routes/users.ts that validates the body against</strong></em></p><p><em><strong>UserPreferencesSchema and writes to user_preferences.</strong></em></p><p><em><strong>Done when: the new route test passes.&#8221;</strong></em></p><p>Specific file. Specific interface. Specific check.</p><p>The<a href="https://www.runpane.com/blog/ai-native-development-workflow"> Pane team</a> scores every plan on a 1-10 confidence scale for one-pass implementation success. Below 8, iterate. Their rules: no aspirations, only instructions. No open questions (if something is unresolved, stop and research first). And if a plan is too big for one session, split it. Oversized plans are where the death loop starts.</p><h3><strong>Stage 3: Parallel agents</strong></h3><p>Here are the 3 concepts I use the most to make parallel agents work.</p><p>Once you have a dependency-ordered task list, tasks that don&#8217;t share files can run at the same time. The thing that used to block this was filesystem collisions. The fix has been sitting in<a href="https://git-scm.com/docs/git-worktree"> git since 2015</a>.</p><h4><strong>Git worktrees</strong></h4><p>One command. Sub-second. The new directory is a fully independent working tree on its own branch, sharing the same .git object store. No re-cloning. Disk cost is just for your working files.</p><p><code>git worktree add .worktrees/feature-auth -b session/feature-auth</code></p><p>Each agent gets a clean branch, zero visibility into other agents&#8217; uncommitted changes, and full ability to run tests independently.</p><p>When done:</p><p><code>git worktree remove --force .worktrees/feature-auth</code></p><p>The branch stays if there are commits to review. Otherwise, it&#8217;s gone.</p><p>This primitive from 2015 that nobody cared about until this year now underpins several independent tools:</p><ul><li><p><strong><a href="https://github.com/mixpeek/amux">amux</a></strong> runs up to 30 Claude Code agents in parallel. Uses SQLite compare-and-swap for atomic task claiming. No Redis. No Kubernetes. Just a WHERE clause and SQLite&#8217;s write lock.</p></li><li><p><strong><a href="https://github.com/generalaction/emdash">Emdash</a></strong> (YC W26) is an open-source desktop app supporting 20+ CLI providers, including Claude Code, Codex, and Gemini CLI, with direct integration into Linear, GitHub, and Jira, plus SSH to remote machines.</p></li><li><p><strong><a href="https://github.com/Dcouple-Inc/Pane">Pane</a></strong> is open-source, from the Doozy founders. Same team behind the 300k-line monorepo. Cross-platform, agent-agnostic, keyboard-first.</p></li></ul><p>All of these solutions are great, but in reality, to get started, none of them are required.<br>A task file and a terminal per worktree gets it done.</p><h4><strong>Scoping agents</strong></h4><p>Every agent session starts with the task description from the plan, the specific files listed in the task, and the relevant section of the spec.</p><p><em><strong># Task: Add useAuth hook</strong></em></p><p><em><strong>Files to read:</strong></em></p><p><em><strong>- src/services/authService.ts (existing service to wrap)</strong></em></p><p><em><strong>- src/hooks/ (existing hook patterns to follow)</strong></em></p><p><em><strong>- src/components/LoginButton.tsx (file to update)</strong></em></p><p><em><strong>Constraints: Do not modify authService.ts.</strong></em></p><p><em><strong>Done: npm run typecheck passes, LoginButton uses useAuth.</strong></em></p><p>The agent can&#8217;t drift into adjacent work because adjacent work isn&#8217;t in its context. It either completes the task or fails clearly.</p><p>Ten 20-turn sessions instead of one 200-turn session.</p><h3><strong>Integration checks</strong></h3><p>TypeScript strict mode, npm run typecheck, and lint are your coordination layer across parallel agents. An agent&#8217;s work isn&#8217;t done until the checks pass. This prevents a type error in one worktree from silently propagating when branches merge. This scales across languages.</p><p>Try to enforce this per task: implement, typecheck, lint, format, and fix all issues before proceeding. After all tasks finish, a reviewer subagent reruns everything and verifies that the plan was completed.</p><p>Human review stays in the loop for architectural decisions, ambiguous acceptance criteria, and code that&#8217;s syntactically valid but semantically wrong. Automated checks catch everything describable as a rule. They don&#8217;t catch everything.</p><h3><strong>What this still doesn&#8217;t fix</strong></h3><p>Agents still hallucinate library APIs. They&#8217;ll write syntactically correct code against an API that changed in the last major version. The planning stage reduces this by including research tasks with URLs, but it doesn&#8217;t eliminate it. Verify unfamiliar library usage against docs before shipping.</p><p>The spec quality ceiling is your knowledge. If you don&#8217;t understand your codebase well enough to write a clear spec, the agent won&#8217;t either. The planning phase surfaces this. If you can&#8217;t finish the plan without open questions, you need to learn more before you start.</p><p>Merge conflicts still happen when two tasks share a file the plan didn&#8217;t account for. Worktrees stop filesystem collisions. They don&#8217;t do design work.</p><p>The tooling layer is moving fast.<a href="https://git-scm.com/docs/git-worktree"> Git worktrees</a> are stable. The orchestration tools built on top of them aren&#8217;t. Build your workflow around git worktree add, not the wrapper tool.</p><p>Context pollution goes both ways. Too little context and the agent hallucinates your conventions. Too much, and the real rules get buried. The same principle applies to task files: dense, explicit, and short.</p><p>Entropy compounds. Incomplete refactors, mixed conventions, dead code. All of it degrades agent performance on the next feature because the agent has to reason about a messier codebase. This workflow doesn&#8217;t fix that.</p><h3><strong>Where to start this week</strong></h3><p>Don&#8217;t adopt all three stages at once.</p><p>Start with Stage 2. Before your next AI coding session, spend 10 minutes writing a task plan. Three things:</p><ol><li><p>Which files does this touch (name them)</p></li><li><p>What it should NOT do (scope the blast radius)</p></li><li><p>The done signal (what command passes when it&#8217;s complete?)</p></li></ol><p>No new tools. No worktrees yet. Write it down first.</p><p>Once that&#8217;s a habit, add Stage 1. The spec forces you to resolve assumptions before the agent makes them for you.<a href="https://harper.blog/2025/02/16/my-llm-codegen-workflow-atm/"> </a>This + a 15-minute planning session will save you 2+ hours of correction.</p><p>For parallel execution: git worktree add before you open a second tab.<br>One command, isolated branch, no collisions.</p><div class="callout-block" data-callout="true"><p><strong><a href="https://go.hungryminds.dev/agentic-loop-starter-kit">I put together a starter kit with every template from this post</a></strong>: the spec, the task planner prompt, the agent scoping format, the worktree setup script, and a lean CLAUDE.md ready to drop into any repo.</p></div><div><hr></div><h1 style="text-align: center;"><strong>This Week in the News</strong></h1><ul><li><p>&#129504; <strong><a href="https://poolside.ai/models">A new contender just entered the coding model race</a></strong>: Jason Warner, GitHub&#8217;s former CTO&#8217;s startup, Poolside has released a new set of agentic coding models built specifically for software engineering workflows. This is a focused bet on where development is heading, with models designed for control, performance, and real-world coding tasks rather than general-purpose use.</p></li><li><p>&#9881;&#65039; <strong><a href="https://cursor.com/blog/typescript-sdk">Cursor just turned its agents into an API</a></strong>: Cursor&#8217;s new TypeScript SDK lets you invoke its coding agents from CI pipelines, backend services, or even your own product. This moves agents out of the editor and into the system itself, where they can run tasks, automate workflows, and become part of how software gets built.</p></li><li><p>&#9883;&#65039; <strong><a href="https://saschb2b.com/blog/react-compiler-year-in-review">React is still trying to automate performance</a></strong>: A year into the React Compiler experiment, the direction is becoming clearer. The goal is to shift performance optimization away from developers by letting the compiler handle memoization and rendering decisions, reducing the need for manual tuning in complex applications.</p></li><li><p>&#128994; <strong><a href="https://github.com/nodejs/node/pull/62526">Node 26 hit a delay, but Temporal is still close</a></strong>: Node 26.0 was expected to land with the Temporal API enabled by default, but a <a href="https://nodeweekly.com/link/184535/web">macOS-related problem</a> led to a last-minute delay. A <a href="https://nodeweekly.com/link/184536/web">fix is already in progress</a> and <a href="https://nodeweekly.com/link/184537/web">a new release candidate is available</a>, keeping Temporal on track to become part of the standard Node experience.</p></li><li><p>&#129504; <strong><a href="https://openai.com/index/where-the-goblins-came-from">Where the goblins in ChatGPT actually came from</a></strong>: OpenAI dug into a strange behavior where its models kept referencing goblins and other creatures in unrelated contexts. The cause wasn&#8217;t a bug in the usual sense. It came from subtle training incentives, especially around personality tuning, where certain kinds of metaphors were rewarded more than expected and then spread across the model. It&#8217;s a small, almost funny example, but it points to something deeper. Model behavior is shaped by many tiny signals, and those signals don&#8217;t always stay contained.</p><div><hr></div></li></ul><h1 style="text-align: center;"><strong>Beyond the Headlines</strong></h1><ul><li><p>&#129513; <strong><a href="https://openai.com/index/open-source-codex-orchestration-symphony/">Coding is shifting from prompts to orchestration</a></strong>: This piece makes it clear that the real shift is not better prompts, but better coordination. Codex is evolving into a system that orchestrates multiple steps, tools, and agents to complete work. The focus is no longer on generating code, but on managing how that code gets produced.</p></li><li><p>&#9888;&#65039; <strong><a href="https://x.com/lifeof_jer/status/2048103471019434248">When output looks right but meaning drifts</a></strong>: A small example shows how generated output can subtly drift from the original intent while still looking correct. Nothing is obviously broken, which is exactly why it gets through. This is the kind of failure that does not show up in syntax or tests, but in meaning.</p></li><li><p>&#129504; <strong><a href="https://blog.happyfellow.dev/simulacrum-of-knowledge-work/">Work that looks complete but lacks depth</a>: </strong>This piece explores how modern tools can produce outputs that resemble real knowledge work without the depth behind them. The results look finished, but the reasoning is often shallow. That gap becomes clear the moment judgment is required.</p></li><li><p>&#128272; <strong><a href="https://muffin.ink/blog/scratch-svg-sanitization/">SVGs are still an easy way to get security wrong</a></strong>: SVGs look harmless, but they can carry scripts and unexpected behavior if not handled carefully. This write-up shows how common sanitization approaches fail and why this issue keeps slipping into production systems.</p></li><li><p>&#9883;&#65039; <strong><a href="https://certificates.dev/blog/accessibility-in-react-common-mistakes-and-how-to-fix-them">Most React accessibility issues are small and avoidable</a>: </strong>Accessibility problems in React apps rarely come from complex logic. They come from small gaps like missing labels, broken semantics, and poor keyboard support. These are easy to miss and just as easy to fix once you know where to look.</p><div><hr></div></li></ul><h1 style="text-align: center;"><strong>Tool of the Week</strong></h1><p>&#127916; <strong><a href="https://www.joshwcomeau.com/animation/scroll-driven-animations">Scroll-driven animations that finally feel natural</a></strong></p><p>Most scroll animations feel disconnected because they rely on timelines instead of user input. This guide shows how to tie motion directly to scroll position, which makes interactions smoother and easier to reason about. It&#8217;s a small shift in approach that fixes a surprisingly common UI problem.</p><p><em>That&#8217;s all for this week. Have any ideas you want to see in the next article? Hit Reply!</em></p><p>Cheers!</p><p>Editor-in-chief,</p><p>Kinnari Chohan</p><div><hr></div><p><strong>&#128075; <a href="https://landing.packtpub.com/sponsorship-landing-page/">Advertise with us</a></strong><br><strong> </strong>Interested in sponsoring this newsletter and reaching a highly engaged audience of tech professionals? Simply reply to this email, and our team will get in touch with the next steps.</p>]]></content:encoded></item><item><title><![CDATA[WebDevPro #137: Why Blocking Code Breaks Node.js Performance ]]></title><description><![CDATA[Crafting the Web: Tips, Tools, and Trends for Developers]]></description><link>https://packtwebdevpro.substack.com/p/webdevpro-137-why-blocking-code-breaks</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/webdevpro-137-why-blocking-code-breaks</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Mon, 27 Apr 2026 14:01:50 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!-Epb!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c609e43-4006-496a-9adf-84620ff6b584_500x500.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 style="text-align: center;"><strong><a href="https://www.vpdae.com/redirect/7au88233yznh73di5miqvjri992">Catch the latest HubSpot Developer Platform updates in Spring Spotlight</a></strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CI9M!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e79b42f-482a-4bda-aded-df60011bc089_200x300.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CI9M!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e79b42f-482a-4bda-aded-df60011bc089_200x300.jpeg 424w, https://substackcdn.com/image/fetch/$s_!CI9M!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e79b42f-482a-4bda-aded-df60011bc089_200x300.jpeg 848w, https://substackcdn.com/image/fetch/$s_!CI9M!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e79b42f-482a-4bda-aded-df60011bc089_200x300.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!CI9M!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e79b42f-482a-4bda-aded-df60011bc089_200x300.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CI9M!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e79b42f-482a-4bda-aded-df60011bc089_200x300.jpeg" width="200" height="300" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1e79b42f-482a-4bda-aded-df60011bc089_200x300.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:300,&quot;width&quot;:200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Spotlight developer platform&quot;,&quot;title&quot;:&quot;Spotlight developer platform&quot;,&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="Spotlight developer platform" title="Spotlight developer platform" srcset="https://substackcdn.com/image/fetch/$s_!CI9M!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e79b42f-482a-4bda-aded-df60011bc089_200x300.jpeg 424w, https://substackcdn.com/image/fetch/$s_!CI9M!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e79b42f-482a-4bda-aded-df60011bc089_200x300.jpeg 848w, https://substackcdn.com/image/fetch/$s_!CI9M!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e79b42f-482a-4bda-aded-df60011bc089_200x300.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!CI9M!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e79b42f-482a-4bda-aded-df60011bc089_200x300.jpeg 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>Spring Spotlight 2026 is live, and we&#8217;ve rounded up the top updates for developers. See what&#8217;s new for the HubSpot Developer Platform! Ship faster with AI coding tools like Cursor, Claude Code, and Codex.</p><p>Build MCP-powered AI connectors, run serverless functions with support for UI extensions, and use date-based versioning to streamline roadmap planning.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://developers.hubspot.com/spotlight?utm_campaign=41988443-DevRel%20%7C%20Spotlight%20%7C%20Spring%202026&amp;utm_source=email&amp;utm_medium=email&amp;utm_content=paved-newsletters&quot;,&quot;text&quot;:&quot;Explore Now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://developers.hubspot.com/spotlight?utm_campaign=41988443-DevRel%20%7C%20Spotlight%20%7C%20Spring%202026&amp;utm_source=email&amp;utm_medium=email&amp;utm_content=paved-newsletters"><span>Explore Now</span></a></p><div><hr></div><p>Welcome to this week&#8217;s issue of WebDevPro!</p><p>Node.js is often chosen for its ability to handle concurrent workloads efficiently. Its event-driven, non-blocking architecture allows applications to process multiple operations without waiting for each one to complete. This model is particularly effective in I/O-heavy systems where responsiveness matters more than sequential execution.</p><p>Because of this, there is a widespread assumption that Node.js applications will perform well under load by default. In practice, that assumption depends on one critical condition: the application must remain non-blocking. Once blocking behavior is introduced, the system begins to behave very differently.</p><p>Blocking code does not always cause immediate failures. In development environments, where concurrency is limited, the system may appear stable. Requests complete, responses are returned, and nothing seems obviously wrong. This creates a false sense of confidence in how the application will behave in production.</p><p>Under real-world conditions, however, multiple operations occur simultaneously, and the event loop becomes a shared dependency across all of them. At that point, the cost of blocking becomes visible. Delays accumulate, responsiveness drops, and the system begins to struggle under load. The issue is not simply that blocking code exists, but how it interacts with the event loop and how that interaction scales.</p><p>Before we get into it, here&#8217;s this week at a glance:</p><ul><li><p><em><strong>&#9883;&#65039; <a href="https://tanstack.com/blog/react-server-components">TanStack Start adds experimental React Server Components support</a></strong></em></p></li><li><p><em><strong>&#129302; <a href="https://code.claude.com/docs/en/routines">Claude introduces &#8220;routines&#8221; for repeatable workflows</a></strong></em></p></li><li><p><em><strong>&#129513; <a href="https://github.github.com/gh-stack/">GitHub introduces stacked PRs in private preview</a></strong></em></p></li><li><p><em><strong>&#127912; <a href="https://nerdy.dev/why-ai-sucks-at-front-end">Why AI still struggles with frontend development</a></strong></em></p></li><li><p><em><strong>&#129529; <a href="https://neciudan.dev/master-eslint-rules">Mastering ESLint rules for better code quality</a></strong></em></p></li><li><p><em><strong>&#127908; <a href="https://www.igalia.com/chats/npmxyz">Inside npmx, a new way to explore the npm ecosystem</a></strong></em></p></li></ul><h3><strong>What blocking means in practice</strong></h3><p>In Node.js, all JavaScript execution happens on a single thread, coordinated by the event loop. The event loop continuously processes tasks by retrieving them from a queue, executing them, and delegating work when possible so that execution can continue without interruption. This model works efficiently because it assumes that tasks will be short-lived and non-blocking.</p><p>Blocking code violates this assumption. When a blocking operation is executed, the event loop cannot proceed to the next task until the current one completes. This does not simply delay a single operation. It prevents all other pending tasks from executing during that time, effectively pausing the system&#8217;s ability to make progress.</p><p>The impact is broader than it first appears. Callbacks that are ready to run remain in the queue. Timers do not fire at expected intervals. Incoming requests must wait before they can even begin execution. What appears to be a local delay becomes a system-wide bottleneck.</p><p>This shared delay is what makes blocking code particularly problematic in Node.js. In systems with multiple threads, delays can be absorbed or distributed. In Node.js, the delay is centralized. A single blocking operation affects everything else that depends on the event loop.</p><h3><strong>Why synchronous APIs are risky in Node.js</strong></h3><p>Synchronous APIs are often attractive because they simplify reasoning about code. Execution flows in a straight line, making it easier to follow and debug. This simplicity can be beneficial in scripts or isolated tasks where concurrency is not a concern.</p><p>In an event-driven system like Node.js, however, synchronous APIs introduce a significant limitation. Because they execute on the main thread, they block the event loop until they complete. During this time, no other operations can be processed, regardless of how unrelated they may be.</p><p>This creates a disconnect between how the code appears and how it behaves under load. The code may look efficient and predictable, but its execution forces all operations into a sequential pattern. Instead of handling multiple tasks concurrently, the system processes them one at a time.</p><p>The result is reduced flexibility in how work is handled. As more operations depend on the event loop, the impact of synchronous APIs becomes more pronounced. What begins as a simple design choice can evolve into a system-wide constraint.</p><h3><strong>CPU-intensive work and hidden blocking</strong></h3><p>Blocking behavior is not limited to I/O operations. CPU-intensive tasks can have an even greater impact, particularly when executed synchronously. These operations consume the main thread for their duration, preventing the event loop from processing other tasks.</p><p>The book illustrates this with a cryptographic key generation example, where a synchronous function is executed repeatedly. Each iteration runs on the main thread, and the cumulative effect is a prolonged period during which the event loop is unavailable.</p><p><code>performance.mark(&#8221;start-sync&#8221;); <br>for (let i = 0; i &lt; 10000; i++) { <br>generateKeyPairSync(&#8221;rsa&#8221;, { <br>modulusLength: 1024, <br>}); <br>} <br>performance.mark(&#8221;end-sync&#8221;); <br>performance.measure(&#8221;generateKeyPairSync&#8221;, &#8220;start-sync&#8221;, &#8220;end-sync&#8221;);</code></p><p>In this scenario, the cost is not just the execution time of a single operation, but the accumulation of blocking across many iterations. The event loop remains occupied for the entire duration, preventing any other work from progressing.</p><p><code>performance.mark(&#8221;start-async&#8221;); <br>for (let i = 0; i &lt; 10000; i++) { <br>generateKeyPair(&#8221;rsa&#8221;, { modulusLength: 1024 }, <br>() =&gt; {}); <br>} <br>performance.mark(&#8221;end-async&#8221;); <br>performance.measure(&#8221;generateKeyPair&#8221;, &#8220;start-async&#8221;, &#8220;end-async&#8221;);</code></p><p>The asynchronous version changes how the work is executed. Instead of occupying the main thread, the operations are delegated, allowing the event loop to remain available. This difference has a direct impact on system responsiveness, especially under load.</p><h3><strong>The performance gap is not theoretical</strong></h3><p>The difference between synchronous and asynchronous execution is not just conceptual. The book demonstrates that the impact can be measured and observed in practice. The synchronous version of the operation takes significantly longer and blocks execution entirely.</p><p>The asynchronous version, by contrast, allows the system to continue processing other tasks while the work is being performed. This leads to better utilization of system resources and improved responsiveness.</p><p>This distinction changes how performance should be evaluated. In Node.js, performance is not only about how quickly a single operation completes. It is about whether the system can continue to process other work during that time.</p><p>A fast operation that blocks the event loop can still degrade system performance if it prevents other tasks from progressing. Conversely, a slower operation that does not block may have less overall impact on system responsiveness.</p><h3><strong>Why this matters more under load</strong></h3><p>Blocking behavior becomes more problematic as concurrency increases. In low-load environments, tasks are processed with minimal overlap, and delays may not be noticeable. The system appears stable because there is little competition for the event loop.</p><p>As the number of concurrent operations grows, the situation changes. Multiple tasks begin to depend on the event loop at the same time. Each task expects to be processed in a timely manner, and blocking operations disrupt this expectation.</p><p>When a blocking operation runs, it prevents the event loop from servicing other tasks. These tasks begin to accumulate in the queue, increasing wait times and reducing overall throughput. The system becomes less responsive as more work is added.</p><p>This is why blocking issues often appear only under load. The system needs sufficient concurrency for the delays to become visible. Once that threshold is reached, the impact becomes more pronounced, and performance begins to degrade more rapidly.</p><h3><strong>Async wrappers do not remove blocking</strong></h3><p>A common misconception is that using asynchronous syntax automatically makes an operation non-blocking. Wrapping a function in async/await or a callback does not change how the underlying work is executed.</p><p>The book emphasizes that async syntax controls how results are handled, not how the work itself is performed. If the underlying operation is synchronous and CPU-intensive, it will still block the event loop.</p><p>This distinction highlights the difference between code structure and execution behavior. A function may appear asynchronous in form while still behaving in a blocking manner in practice.</p><p>Understanding this difference is essential for identifying performance issues. Changing syntax without addressing the underlying execution does not resolve the problem.</p><h3><strong>Reducing work instead of changing execution</strong></h3><p>In some cases, improving performance is not about changing how an operation executes, but reducing how often it runs. The book demonstrates this with an example where repeated computation is replaced with a caching approach.</p><p>Instead of recalculating an expensive result for every request, the system stores the result and updates it periodically. This reduces the number of times the operation is executed, lowering the load on the event loop.</p><p>l<code>et cachedSignature = null; <br>const app = Express();</code></p><p><code>const signingMiddleware = (_req, res, next) =&gt; { <br>if (!cachedSignature) { <br>console.info(&#8221;Signature is not cached&#8221;); <br>cachedSignature = signData(Date.now().toString()); <br>setInterval( <br>() =&gt; (cachedSignature = signData(Date.now().toString())), <br>10000); <br>} <br><br>res.setHeader( <br>&#8220;X-Signature&#8221;, `data=${cachedSignature.data.toString()};kid=${cachedSignature.keyId};sha512=${cachedSignature.signature}`); <br>next(); <br>};</code></p><p>This approach shifts the focus from execution style to execution frequency. By reducing repeated work, the system becomes more efficient without changing how the operation itself is implemented.</p><h3><strong>The real trade-off</strong></h3><p>Blocking code is often easier to write and reason about. Its linear execution model provides clarity and predictability, making it attractive in many situations.</p><p>However, this simplicity comes at a cost in systems that rely on concurrency. Blocking operations limit the ability of the event loop to process multiple tasks efficiently, reducing overall system responsiveness.</p><p>The trade-off is not simply between synchronous and asynchronous code. It is between local simplicity and system-wide performance. A piece of code that is easy to understand in isolation may introduce constraints that affect the entire application.</p><p>As systems scale and concurrency increases, this trade-off becomes more significant. Decisions that seem minor at the code level can have substantial impact at the system level.</p><h3><strong>Key Takeaways</strong></h3><ul><li><p>Blocking code prevents the event loop from processing other tasks, creating system-wide delays.</p></li><li><p>Synchronous APIs introduce constraints that limit concurrency.</p></li><li><p>CPU-intensive operations can block execution even when used with async syntax.</p></li><li><p>Performance in Node.js depends on maintaining event loop availability.</p></li><li><p>Reducing execution frequency can improve efficiency without changing execution style.</p></li></ul><h3><strong>Final Thoughts</strong></h3><p>Node.js relies on a responsive event loop to handle concurrent operations effectively. Blocking code disrupts this model by introducing delays that affect all tasks, not just the one being executed.</p><p>The impact of blocking behavior is not always immediate, but it becomes clear under load. As concurrency increases, the system&#8217;s ability to process work efficiently depends on keeping the event loop free.</p><p>If you&#8217;d like to read more on this, <em><strong><a href="https://www.amazon.com/Node-js-Design-Patterns-production-grade-applications/dp/1803238941/ref=sr_1_2">Node.js Design Patterns</a></strong></em> explores these ideas in depth, especially around asynchronous behavior, performance, and the architectural decisions behind scalable Node.js systems.</p><h1 style="text-align: center;"><strong>This Week in the News</strong></h1><ul><li><p>&#129504; <strong><a href="https://blog.pragmaticengineer.com/the-pulse-tokenmaxxing-as-a-weird-new-trend/?utm_source=chatgpt.com">Tokenmaxxing is the new productivity metric developers are gaming</a></strong>: There&#8217;s a new habit showing up in AI-heavy workflows. Teams are starting to track and even optimize for token usage, treating it as a signal of productivity. Gergely Orosz digs into why that framing breaks down quickly. More tokens don&#8217;t mean better outcomes, just more input. It&#8217;s the same pattern developers have seen before with lines of code and story points, now resurfacing in an AI-shaped form. What&#8217;s interesting here is not the trend itself, but how quickly it appeared. Even with new tools, the instinct to measure the wrong thing hasn&#8217;t changed.</p></li><li><p>&#9889; <strong><a href="https://devblogs.microsoft.com/typescript/announcing-typescript-7-0-beta/">TypeScript 7.0 goes 10x faster with a Go rewrite</a></strong>: The TypeScript team has released the 7.0 beta after spending the past year porting the entire compiler to Go. The result is a version that&#8217;s roughly 10x faster than TypeScript 6.0, while keeping the type-checking behavior structurally the same. For developers, that means no major migration or new errors to worry about. Just significantly faster builds out of the box.</p></li><li><p>&#128994; <strong><a href="https://github.com/nodejs/node/pull/61806">Node.js moves toward Temporal API and stabilizes key features</a>: </strong>Node.js is preparing to support the Temporal API by default, likely landing in the upcoming v26 release. This brings a modern, more reliable alternative to JavaScript&#8217;s existing Date handling into the runtime. At the same time, Node.js 24.15.0 (LTS) marks require(esm), and the module compile cache as stable, and introduces a new --max-heap-size flag. Together, these updates signal continued progress in both runtime capabilities and performance tooling.</p></li><li><p><strong>&#128231; <a href="https://resend.com/blog/react-email-6">React Email 6 simplifies a fragmented ecosystem</a></strong>:<strong> </strong>React Email 6 introduces a major update focused on cleaning up versioning issues across its ecosystem. The release makes it easier to manage dependencies and ensures the CLI and components stay in sync. For teams building email templates with React, this should reduce friction and make the overall workflow more predictable.</p></li></ul><h1 style="text-align: center;"><strong>Beyond the Headlines</strong></h1><ul><li><p>&#9889; <strong><a href="https://voidzero.dev/posts/oxc-angular-compiler">A new Angular compiler built on Oxc</a></strong>: This post explores an experimental Angular compiler powered by <strong>Oxc</strong>, a Rust-based toolchain focused on performance. The goal is to significantly speed up builds and modernize the compilation pipeline. It&#8217;s another signal that JavaScript tooling is steadily moving toward Rust-based infrastructure to push performance boundaries.</p></li><li><p>&#128680; <strong><a href="https://awesomeagents.ai/news/github-fake-stars-investigation/">Investigating fake stars in GitHub repos</a></strong>: This investigation looks into how some GitHub repositories inflate their popularity using fake stars. It highlights how easily perception can be manipulated and why star counts aren&#8217;t always a reliable signal of quality. For developers, it&#8217;s a reminder to evaluate projects based on code, activity, and community, not just metrics.</p></li><li><p><strong>&#127909; <a href="https://www.youtube.com/watch?v=a9_Ud5MFTjU">Rethinking modern web architecture</a></strong>: This talk dives into how modern web architecture is evolving, covering trade-offs in performance, complexity, and developer experience. It offers a broader perspective on how current patterns scale in real-world applications. A useful watch if you&#8217;re thinking beyond frameworks and into long-term system design.</p></li><li><p>&#129513; <strong><a href="https://nesbitt.io/2026/04/16/features-everyone-should-steal-from-npmx.html">Features worth borrowing from npmx</a>: </strong>This article breaks down specific ideas from the npmx project that could inspire better developer tools. It highlights practical features that improve how developers explore and interact with packages. The takeaway is simple. Good tooling often comes from rethinking small UX details.</p></li><li><p><strong>&#128736;&#65039; <a href="https://cursor.com/blog/app-stability">Why app stability matters more than ever</a>: </strong>Cursor shares insights into building stable applications, especially in environments where rapid iteration and AI-assisted development are becoming the norm. The focus is on reducing breakage and maintaining reliability as systems evolve. It&#8217;s a reminder that speed is valuable, but stability is what keeps users and teams productive.</p></li></ul><h1 style="text-align: center;"><strong>Tool of the Week</strong></h1><p>&#127916; <strong><a href="https://animata.design/">Add unique animations to your React apps</a></strong></p><p>Building engaging UIs often means going beyond basic transitions. <strong><a href="https://animata.design/">Animata</a></strong> offers a collection of 100+ animation-focused React components, including effects like animated beams, spreading cards, and even a Slack-style intro screen.</p><p>It&#8217;s a handy resource if you want to add more personality to your UI without building complex animations from scratch.</p><p><em>That&#8217;s all for this week. Have any ideas you want to see in the next article? Hit Reply!</em></p><p>Cheers!</p><p>Editor-in-chief,</p><p>Kinnari Chohan</p><div><hr></div><p><strong>&#128075; <a href="https://landing.packtpub.com/sponsorship-landing-page/">Advertise with us</a></strong><br><strong> </strong>Interested in sponsoring this newsletter and reaching a highly engaged audience of tech professionals? Simply reply to this email, and our team will get in touch with the next steps.</p>]]></content:encoded></item><item><title><![CDATA[WebDevPro #136: Agent Continuous Learning Framework: Build Traces, Refine Context, Iterate with a Harness (like DeerFlow), then Fine‑Tune the Model]]></title><description><![CDATA[By Daniel He, Co&#8209;Author of DeerFlow]]></description><link>https://packtwebdevpro.substack.com/p/webdevpro-136-agent-continuous-learning</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/webdevpro-136-agent-continuous-learning</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Wed, 22 Apr 2026 14:02:37 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!PZU4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92599987-270c-4650-a493-6436d4be045b_1880x940.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to this week&#8217;s bonus issue of WebDevPro!</p><p>DeerFlow is an open&#8209;source SuperAgent framework based on LangGraph, focusing on multi&#8209;agent orchestration, with 60K+ stars on GitHub. Core contributor Daniel He has long been deeply involved in agent workflow design and stateful graph execution, and he is dedicated to pushing autonomous agents to the true limits of production environments.</p><p><em>This article is a speaker feature for an upcoming <strong>FREE</strong> live session hosted by Packt, where the DeerFlow team will walk through how these ideas translate into real systems.</em></p><h1 style="text-align: center;"><strong><a href="https://www.eventbrite.co.uk/e/build-ai-agents-with-deerflow-20-tickets-1987511310833?aff=webdevpro">Build AI Agents with DeerFlow 2.0</a></strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!PZU4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92599987-270c-4650-a493-6436d4be045b_1880x940.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PZU4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92599987-270c-4650-a493-6436d4be045b_1880x940.webp 424w, https://substackcdn.com/image/fetch/$s_!PZU4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92599987-270c-4650-a493-6436d4be045b_1880x940.webp 848w, https://substackcdn.com/image/fetch/$s_!PZU4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92599987-270c-4650-a493-6436d4be045b_1880x940.webp 1272w, https://substackcdn.com/image/fetch/$s_!PZU4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92599987-270c-4650-a493-6436d4be045b_1880x940.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PZU4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92599987-270c-4650-a493-6436d4be045b_1880x940.webp" width="1456" height="728" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/92599987-270c-4650-a493-6436d4be045b_1880x940.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:728,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Deerflow 2.0 FREE workshop &quot;,&quot;title&quot;:&quot;Deerflow 2.0 FREE workshop &quot;,&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="Deerflow 2.0 FREE workshop " title="Deerflow 2.0 FREE workshop " srcset="https://substackcdn.com/image/fetch/$s_!PZU4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92599987-270c-4650-a493-6436d4be045b_1880x940.webp 424w, https://substackcdn.com/image/fetch/$s_!PZU4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92599987-270c-4650-a493-6436d4be045b_1880x940.webp 848w, https://substackcdn.com/image/fetch/$s_!PZU4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92599987-270c-4650-a493-6436d4be045b_1880x940.webp 1272w, https://substackcdn.com/image/fetch/$s_!PZU4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92599987-270c-4650-a493-6436d4be045b_1880x940.webp 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 style="text-align: center;">Expect live demos, including agents that review pull requests and generate full research reports from a single prompt, along with a closer look at how DeerFlow coordinates models like GPT, Gemini, and DeepSeek behind the scenes.</p><p style="text-align: center;">The event is designed for engineers, AI practitioners, product teams, and anyone exploring autonomous workflows or open source agent systems. It also includes insights from the maintainers on how the project evolved from DeerFlow 1.0 to 2.0, what is coming next, and how to get involved.</p><p style="text-align: center;"><strong>&#128197;</strong> <strong><a href="https://www.eventbrite.co.uk/e/build-ai-agents-with-deerflow-20-tickets-1987511310833?aff=webdevpro">Wednesday, May 6 &#8226; 9 AM &#8211; 10:30 AM EDT</a></strong><br><strong>&#127760; <a href="https://www.eventbrite.co.uk/e/build-ai-agents-with-deerflow-20-tickets-1987511310833?aff=webdevpro">Free online event by Packt Publishing</a></strong></p><p style="text-align: center;"><strong><a href="https://www.eventbrite.co.uk/e/build-ai-agents-with-deerflow-20-tickets-1987511310833?aff=webdevpro">Register now</a></strong></p><div><hr></div><p>How exactly can an agent system &#8220;continuously become stronger&#8221;?</p><p>It relies on training data, training infrastructure, and evaluation loops, which makes this kind of continuous improvement a platform-level capability rather than something a typical product team can iterate on frequently.</p><p>Recently, Harrison Chase, the founder of LangChain, <a href="https://x.com/hwchase17/status/2040467997022884194?s=20">posted an X thread</a> that breaks down the Agent Continuous Learning system into three layers: <strong>Model</strong> (model weights), <strong>Harness</strong> (execution mechanism), and <strong>Context</strong> (configurable memory). He then combined this with cutting-edge work such as <strong><a href="https://yoonholee.com/meta-harness/">Meta-Harness</a></strong> and <strong><a href="https://github.com/langchain-ai/deepagents">LangChain Deep Agents</a></strong> to analyze the learning methods, implementation costs, and applicable scenarios of each layer.</p><p>Based on this analysis, a possible action path for product teams is: first, get Traces right, then do Context learning, then establish a Harness optimization loop, and finally consider model fine-tuning.</p><p>The core argument of this article is very clear:</p><p><em>For AI agents, &#8220;continuous learning&#8221; should not be understood as merely updating model weights. An agent system can actually evolve continuously on three levels: Model, Harness, and Context.</em></p><h1><strong>Core Framework: Three-Layer Agent Learning</strong></h1><p>In his thread, Harrison broke down the agentic system into three layers:</p><ul><li><p><strong>Model:</strong> The underlying model itself, which is the weights.</p></li><li><p><strong>Harness:</strong> The &#8220;shell&#8221; that drives the model&#8217;s operation, including agent code, fixed tools, fixed hints, execution loops, etc.</p></li><li><p><strong>Context:</strong> A configurable context located outside of the harness, such as memory files, skills, user configurations, and team configurations.</p></li></ul><p>The value of this definition lies in the fact that it expands &#8220;learning&#8221; from a single model training problem into a complete systems engineering problem.</p><h1><strong>Layer-by-layer interpretation</strong></h1><p><strong>1. Model layer: The most traditional, but also the most complex layer.</strong></p><p>This layer corresponds to continuous learning, which is most familiar to everyone:</p><ul><li><p>Update weights using methods such as SFT and RL.</p></li><li><p>It is also possible to use a more fine-grained adaptation method, such as LoRA.</p></li><li><p>The goal is to make the model perform better on new tasks.</p></li></ul><p>However, an old problem persists: <strong>catastrophic forgetting</strong>. That is, after the model learns new things, its old abilities actually degenerate.</p><p>Daniel&#8217;s judgment is:</p><ul><li><p>For most teams, the Model layer has the highest continuous learning cost.</p></li><li><p>It relies on training data, training infrastructure, evaluation loop, and model deployment mechanism.</p></li><li><p>This is more like a platform-level capability than a routine method that a typical product team can frequently iterate upon.</p></li></ul><p>So while Harrison acknowledges the importance of the model layer, his real focus is not there.</p><p><strong>2. Harness Layer: The most underestimated leverage point in agent engineering over the past year.</strong></p><p>&#8220;Harness&#8221; does not refer to the model itself, but rather &#8220;how the model is used&#8221;:</p><ul><li><p>How to write system prompts</p></li><li><p>How to expose tools to the model</p></li><li><p>How to organize loop calls</p></li><li><p>When to truncate the context, when to retry, and when to determine if the task is complete</p></li><li><p>Which logs and traces are saved for later analysis</p></li></ul><p>Harrison specifically mentions the work at https://yoonholee.com/meta-harness/ in his article. Its main idea can be summarized as follows:</p><ol><li><p>Run the agent on a batch of tasks.</p></li><li><p>Collect complete execution logs and scores.</p></li><li><p>Store these historical candidates, source code, and execution traces in the filesystem.</p></li><li><p>Then, have a coding agent read these materials and propose new harness modifications.</p></li><li><p>Evaluating the new harness and continuing its iterations.</p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AfbA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ea11c4-0cf2-4541-9c61-4302d608eaf0_1080x385.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AfbA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ea11c4-0cf2-4541-9c61-4302d608eaf0_1080x385.webp 424w, https://substackcdn.com/image/fetch/$s_!AfbA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ea11c4-0cf2-4541-9c61-4302d608eaf0_1080x385.webp 848w, https://substackcdn.com/image/fetch/$s_!AfbA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ea11c4-0cf2-4541-9c61-4302d608eaf0_1080x385.webp 1272w, https://substackcdn.com/image/fetch/$s_!AfbA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ea11c4-0cf2-4541-9c61-4302d608eaf0_1080x385.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!AfbA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ea11c4-0cf2-4541-9c61-4302d608eaf0_1080x385.webp" width="1080" height="385" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c6ea11c4-0cf2-4541-9c61-4302d608eaf0_1080x385.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:385,&quot;width&quot;:1080,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!AfbA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ea11c4-0cf2-4541-9c61-4302d608eaf0_1080x385.webp 424w, https://substackcdn.com/image/fetch/$s_!AfbA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ea11c4-0cf2-4541-9c61-4302d608eaf0_1080x385.webp 848w, https://substackcdn.com/image/fetch/$s_!AfbA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ea11c4-0cf2-4541-9c61-4302d608eaf0_1080x385.webp 1272w, https://substackcdn.com/image/fetch/$s_!AfbA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ea11c4-0cf2-4541-9c61-4302d608eaf0_1080x385.webp 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>This is important because it illustrates:</p><ul><li><p>Agent evolution can be achieved without changing the model, only the runtime framework.</p></li><li><p>The truly high-value optimization targets are often the &#8220;execution mechanism&#8221; rather than the &#8220;parameters&#8221;.</p></li><li><p>The more complete the traces, the more harness optimization resembles an engineering iteration rather than a matter of guesswork and prompt adjustments.</p></li></ul><p>The official <a href="https://yoonholee.com/meta-harness/">Meta-Harness</a> page also presents strong results: it emphasizes its key difference by allowing the optimizer to see the complete historical code, scores, and execution traces, rather than just a summary. The authors claim that this &#8220;filesystem-level context&#8221; can increase the available diagnostic information for each round of optimization by an order of magnitude compared to traditional methods.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CeI6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2fd5b9-63fd-4663-a144-598d992ab2f3_1080x583.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CeI6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2fd5b9-63fd-4663-a144-598d992ab2f3_1080x583.webp 424w, https://substackcdn.com/image/fetch/$s_!CeI6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2fd5b9-63fd-4663-a144-598d992ab2f3_1080x583.webp 848w, https://substackcdn.com/image/fetch/$s_!CeI6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2fd5b9-63fd-4663-a144-598d992ab2f3_1080x583.webp 1272w, https://substackcdn.com/image/fetch/$s_!CeI6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2fd5b9-63fd-4663-a144-598d992ab2f3_1080x583.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CeI6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2fd5b9-63fd-4663-a144-598d992ab2f3_1080x583.webp" width="1080" height="583" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9d2fd5b9-63fd-4663-a144-598d992ab2f3_1080x583.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:583,&quot;width&quot;:1080,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!CeI6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2fd5b9-63fd-4663-a144-598d992ab2f3_1080x583.webp 424w, https://substackcdn.com/image/fetch/$s_!CeI6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2fd5b9-63fd-4663-a144-598d992ab2f3_1080x583.webp 848w, https://substackcdn.com/image/fetch/$s_!CeI6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2fd5b9-63fd-4663-a144-598d992ab2f3_1080x583.webp 1272w, https://substackcdn.com/image/fetch/$s_!CeI6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d2fd5b9-63fd-4663-a144-598d992ab2f3_1080x583.webp 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><strong>3. Context Layer: Closest to the business logic, and best suited for initial implementation</strong></p><p>Harrison defines Context as content located <em>outside</em> of the harness used to configure the agent, for example:</p><ul><li><p>Instructions</p></li><li><p>Skills</p></li><li><p>Tools</p></li><li><p>Memory files</p></li><li><p>User preferences</p></li><li><p>Team rules</p></li></ul><p>The key to this layer is not &#8220;what the model has learned&#8221;, but &#8220;what the system has remembered and how to continue using it in subsequent sessions&#8221;.</p><p>The official documentation for LangChain Deep Agents explains this in great detail. It supports:</p><ul><li><p><strong>Agent-scoped memory</strong>: All users share the same agent memory.</p></li><li><p><strong>User-scoped memory</strong>: Each user has their own independent memory.</p></li><li><p><strong>Online update</strong>: Write directly to memory during session</p></li><li><p><strong>Backend organization</strong>: Performing consolidation outside the session</p></li><li><p><strong>Skills</strong> are a form of procedural memory, loaded only when needed.</p></li></ul><p>This shows that the Context layer is not as simple as &#8220;adding more prompts&#8221;, but a persistent, hierarchical, readable, writable, and searchable memory system.</p><h1><strong>Two examples from the author</strong></h1><p>Harrison used two mappings in the article, first for Claude Code:</p><ul><li><p><strong>Models:</strong> Claude Sonnet, and so on</p></li><li><p><strong>Harness:</strong> Claude Code itself</p></li><li><p><strong>User context:</strong> CLAUDE.md, /skills, mcp.json</p></li></ul><p>This breakdown is very practical because it directly illustrates:</p><ul><li><p>Your perception that &#8220;Claude Code has become smarter&#8221; may not necessarily be due to changes in the model weights;</p></li><li><p>It&#8217;s also possible that the harness has been changed;</p></li><li><p>Or perhaps you&#8217;ve configured its context better;</p></li></ul><p>And again for OpenClaw:</p><ul><li><p><strong>Model:</strong> Can accept multiple models</p></li><li><p><strong>Harness:</strong> Pi (powers OpenClaw) plus some running scaffolding</p></li><li><p><strong>Agent context</strong>: SOUL.md and skills from ClawHub</p></li></ul><p>OpenClaw&#8217;s public documentation says:</p><ul><li><p>SOUL.md is officially defined as the personality and tone configuration file for the agent</p></li><li><p>ClawHub is defined as a public registry of OpenClaw skills/plugins</p></li></ul><p>This precisely confirms Harrison&#8217;s point: the &#8220;continuous learning&#8221; of many agent systems essentially occurs at the configurable context layer, rather than the model fine-tuning layer.</p><h1><strong>The paradigm shift this article aims to promote</strong></h1><p>To summarize this article into a single sentence:</p><p>An agent&#8217;s continuous learning is shifting from &#8220;training the model&#8221; to &#8220;optimizing the entire system&#8221;.</p><p>There are at least three changes here:</p><p><strong>1. The learning objective shifts from weights to system behavior.</strong></p><p>Traditional LLM continuous learning focuses more on:</p><ul><li><p>Has the loss decreased?</p></li><li><p>Has the benchmark improved?</p></li></ul><p>Agent continuous learning focuses more on:</p><ul><li><p>Are they better at using tools?</p></li><li><p>Are they better at planning steps?</p></li><li><p>Can we improve our execution strategies by learning from past failures?</p></li><li><p>Do we have a better understanding of the preferences of current users, teams, or organizations?</p></li></ul><p><strong>2. The learning unit is shifting from a single model to a hierarchical architecture.</strong></p><p>Within the same agent system, the learning frequency and cost of different layers are completely different:</p><ul><li><p>Model: Low frequency, high cost, platform level</p></li><li><p>Harness: Mid-frequency, engineering-driven, measurable</p></li><li><p>Context: High frequency, business-driven, most likely to occur online</p></li></ul><p>This means that continuous learning should not have just one master switch, but rather three different mechanisms.</p><p><strong>3. Traces become a unified fuel.</strong></p><p>Harrison repeatedly emphasizes &#8220;traces&#8221; at the end of the article. This is one of the most crucial infrastructure assessments in the entire text.</p><p>The reason is straightforward:</p><ul><li><p>To modify the model, you need traces as a source of training/preference data</p></li><li><p>To improve harnessing, you need traces as diagnostic material for failures</p></li><li><p>To modify the context, you need traces as source material for experience extraction</p></li></ul><p>In other words, without high-quality traces, there is no high-quality agent learning loop.</p><h1><strong>Some personal judgments</strong></h1><p><strong>1. The Context layer will be the first to become widespread.</strong></p><p>Daniel believes that the Context layer, rather than the Model layer, will be the first of the three layers to be widely implemented.</p><p>Reasons:</p><ul><li><p>No training required</p></li><li><p>The most direct impact on business returns</p></li><li><p>Isolation can be done by user / team / org</p></li><li><p>Easy to manage permissions and rollback</p></li><li><p>Easier to meet the controllability requirements of enterprise systems</p></li></ul><p>Many capabilities that are packaged today as &#8220;the agent can remember&#8221; essentially belong to this level.</p><p><strong>2. The Harness layer will become the focus of the next round of agent infrastructure competition.</strong></p><p>If 2024 was mainly about who could get their agent up and running first, then 2026 will be more about:</p><ul><li><p>Whose harness is more stable?</p></li><li><p>Whose traces are more complete?</p></li><li><p>Whose evaluation and replay system is more closed-loop?</p></li><li><p>Who can quickly incorporate failure cases into the next version of agent behavior improvement?</p></li></ul><p>This is why work like Meta-Harness is worth paying attention to. It represents a very engineering-oriented approach: letting the agent help you change the agent.</p><h1><strong>Practical reflections on your team&#8217;s development of agent products</strong></h1><p>If your team is planning to incorporate &#8220;continuous learning&#8221; into its agent roadmap, Daniel recommend proceeding in the following order:</p><p><strong>Phase 1: First, get the traces right</strong></p><ul><li><p>Unified recording of task input, tool calls, key intermediate states, output results, and human feedback</p></li><li><p>Preserve reviewable evidence for failed tasks, rather than just reporting an error</p></li><li><p>Add user/org/task/version dimension tags to traces</p></li></ul><p><strong>Phase 2: Prioritize context learning</strong></p><ul><li><p>Start with user preferences, team rules, glossary, and standard operating procedures (SOPs)</p></li><li><p>Distinguish between read-only memory and writable memory</p></li><li><p>Define the scope: which is user-level and which is org-level</p></li><li><p>Support both online writing and offline defragmentation update paths</p></li></ul><p><strong>Phase 3: Establish the Harness optimization loop</strong></p><ul><li><p>Run the agent continuously on a standard task set</p></li><li><p>Perform A/B testing and automated evaluation on the harness version</p></li><li><p>The coding agent reads traces to help propose candidates for harness modification</p></li><li><p>Establish a rollback mechanism to prevent situations where changing the prompt might seem convenient in the short term, but ultimately leads to decreased overall stability</p></li></ul><p><strong>Phase 4: Consider model-level learning only as a last resort</strong></p><ul><li><p>Only when you have accumulated enough high-quality traces</p></li><li><p>Furthermore, optimizations at the harness/context layer are nearing their limits</p></li></ul><h1><strong>A reusable decision framework</strong></h1><p>When faced with the question &#8220;How should an agent undergo learning?&#8221;, you can first ask four questions:</p><ol><li><p>What needs to be changed this time? Is it the model capabilities, the operating mechanism, or the configurable memory?</p></li><li><p>Should this change apply to the agent, user, or org scope?</p></li><li><p>Should this update occur immediately during runtime, or should it be processed in an offline task before taking effect?</p></li><li><p>Are there enough complete traces to support an assessment of whether this learning was truly effective?</p></li></ol><p>If these four questions cannot be answered clearly, the so-called &#8220;continuous learning&#8221; is most likely just a vague slogan.</p><h1><strong>Conclusion</strong></h1><p>The value of Harrison Chase&#8217;s post and accompanying article lies not in proposing a completely new algorithm, but in breaking down agent continuous learning into a more practical three-layer framework:</p><ul><li><p>Model learning addresses underlying capabilities</p></li><li><p>Harness learning addresses the execution mechanism</p></li><li><p>Context learning addresses memory and personalization</p></li></ul><p>The two things that the product team should act on immediately are not training the model, but rather:</p><ul><li><p>Build the infrastructure for traces</p></li><li><p>Productize the context and harness learning loop</p></li></ul><p>This is also Daniel&#8217;s core conclusion for this article: stronger agents in the future will not necessarily come from larger models, but are more likely to come from systems that are better at &#8220;reviewing, remembering, and reconstructing&#8221;.</p><div><hr></div><p><em>Want to know more about how to turn your prompts into workflows with an agent harness? Join us for a live demonstration of <strong>DeerFlow 2.0</strong> on <strong>6th May</strong>! </em><br><em><strong><a href="https://www.eventbrite.co.uk/e/build-ai-agents-with-deerflow-20-tickets-1987511310833?aff=webdevpro">Register now!</a></strong></em></p><div><hr></div><p><em>That&#8217;s all for this week. Have any ideas you want to see in the next article? Hit Reply!</em></p><p>Cheers!</p><p>Editor-in-chief,</p><p>Kinnari Chohan</p><div><hr></div><p><strong>&#128075; <a href="https://landing.packtpub.com/sponsorship-landing-page/">Advertise with us</a></strong><br><strong> </strong>Interested in sponsoring this newsletter and reaching a highly engaged audience of tech professionals? Simply reply to this email, and our team will get in touch with the next steps.</p>]]></content:encoded></item><item><title><![CDATA[WebDevPro #135 MCP Is Redefining How We Expose Backend Capabilities]]></title><description><![CDATA[Crafting the Web: Tips, Tools, and Trends for Developers]]></description><link>https://packtwebdevpro.substack.com/p/webdevpro-135-mcp-is-redefining-how</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/webdevpro-135-mcp-is-redefining-how</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Mon, 20 Apr 2026 14:03:56 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!aYXj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe597e801-090b-4c8e-a90e-ede8b0f8238e_800x400.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to this week&#8217;s issue of WebDevPro!</p><p>For years, web development has revolved around a stable contract: define endpoints, shape responses, and let clients call into your system.</p><p>That model still works, but it starts to feel strained when the client is no longer just a browser or a mobile app, but an AI system that needs to discover, interpret, and use your backend dynamically.</p><p>Most AI integrations today are still improvised. Teams wire up function calling, patch together tool layers, and build thin wrappers around internal APIs. The result, therefore, is predictable: duplication, brittle integrations, and systems that are hard to extend.</p><p>MCP, on the other hand, introduces a different approach. Instead of treating AI as an add-on, it defines a standard way to expose capabilities so clients can discover and use them reliably.</p><p>This is not just an AI story. It is an architectural shift that web developers should understand early.</p><p>Before we get into it, here&#8217;s this week at a glance:</p><ul><li><p><em><strong>&#9883;&#65039; <a href="https://tanstack.com/blog/react-server-components">TanStack Start adds experimental React Server Components support</a></strong></em></p></li><li><p><em><strong>&#129302; <a href="https://code.claude.com/docs/en/routines">Claude introduces &#8220;routines&#8221; for repeatable workflows</a></strong></em></p></li><li><p><em><strong>&#129513; <a href="https://github.github.com/gh-stack/">GitHub introduces stacked PRs in private preview</a></strong></em></p></li><li><p><em><strong>&#127912; <a href="https://nerdy.dev/why-ai-sucks-at-front-end">Why AI still struggles with frontend development</a></strong></em></p></li><li><p><em><strong>&#129529; <a href="https://neciudan.dev/master-eslint-rules">Mastering ESLint rules for better code quality</a></strong></em></p></li><li><p><em><strong>&#127908; <a href="https://www.igalia.com/chats/npmxyz">Inside npmx, a new way to explore the npm ecosystem</a></strong></em></p></li></ul><h3><strong>From Endpoints to Capabilities</strong></h3><p>Traditional APIs are built around endpoints. You define routes, attach handlers, and document how clients should call them. MCP shifts the focus from endpoints to <strong>capabilities</strong>.</p><p>Instead of exposing a set of URLs, you expose:</p><ul><li><p>Tools</p></li><li><p>Resources</p></li><li><p>Templates</p></li></ul><p>They form the core building blocks of MCP, separating computation, context, and reusable instruction patterns.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!o_wX!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32d53cb6-abf7-461d-bcc8-228f96466281_670x235.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!o_wX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32d53cb6-abf7-461d-bcc8-228f96466281_670x235.png 424w, https://substackcdn.com/image/fetch/$s_!o_wX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32d53cb6-abf7-461d-bcc8-228f96466281_670x235.png 848w, https://substackcdn.com/image/fetch/$s_!o_wX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32d53cb6-abf7-461d-bcc8-228f96466281_670x235.png 1272w, https://substackcdn.com/image/fetch/$s_!o_wX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32d53cb6-abf7-461d-bcc8-228f96466281_670x235.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!o_wX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32d53cb6-abf7-461d-bcc8-228f96466281_670x235.png" width="670" height="235" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/32d53cb6-abf7-461d-bcc8-228f96466281_670x235.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:235,&quot;width&quot;:670,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!o_wX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32d53cb6-abf7-461d-bcc8-228f96466281_670x235.png 424w, https://substackcdn.com/image/fetch/$s_!o_wX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32d53cb6-abf7-461d-bcc8-228f96466281_670x235.png 848w, https://substackcdn.com/image/fetch/$s_!o_wX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32d53cb6-abf7-461d-bcc8-228f96466281_670x235.png 1272w, https://substackcdn.com/image/fetch/$s_!o_wX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32d53cb6-abf7-461d-bcc8-228f96466281_670x235.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Endpoints assume the client already knows what exists. Capabilities allow the client to <strong>discover what is available at runtime</strong>.</p><p>That removes a lot of implicit coupling between systems. It also reduces the need to hardcode assumptions into every integration.</p><h3><strong>A Familiar Model, Framed Differently</strong></h3><p>At a high level, MCP follows a structure that will feel familiar:</p><ul><li><p>A <strong>server</strong> exposes functionality</p></li><li><p>A <strong>client</strong> connects and invokes it</p></li><li><p>A <strong>host</strong> provides the environment where interactions happen</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xtJb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19ef19ee-e09c-4a22-b67e-dbb89eba7b40_717x307.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xtJb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19ef19ee-e09c-4a22-b67e-dbb89eba7b40_717x307.png 424w, https://substackcdn.com/image/fetch/$s_!xtJb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19ef19ee-e09c-4a22-b67e-dbb89eba7b40_717x307.png 848w, https://substackcdn.com/image/fetch/$s_!xtJb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19ef19ee-e09c-4a22-b67e-dbb89eba7b40_717x307.png 1272w, https://substackcdn.com/image/fetch/$s_!xtJb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19ef19ee-e09c-4a22-b67e-dbb89eba7b40_717x307.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xtJb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19ef19ee-e09c-4a22-b67e-dbb89eba7b40_717x307.png" width="717" height="307" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/19ef19ee-e09c-4a22-b67e-dbb89eba7b40_717x307.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:307,&quot;width&quot;:717,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!xtJb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19ef19ee-e09c-4a22-b67e-dbb89eba7b40_717x307.png 424w, https://substackcdn.com/image/fetch/$s_!xtJb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19ef19ee-e09c-4a22-b67e-dbb89eba7b40_717x307.png 848w, https://substackcdn.com/image/fetch/$s_!xtJb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19ef19ee-e09c-4a22-b67e-dbb89eba7b40_717x307.png 1272w, https://substackcdn.com/image/fetch/$s_!xtJb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19ef19ee-e09c-4a22-b67e-dbb89eba7b40_717x307.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>Communication happens through structured messages, with an explicit handshake where both sides exchange capabilities before doing any work. The initialize-initialized handshake ensures both client and server agree on capabilities before any interaction begins.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xfz0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0c6600-1d59-4e30-ab5a-6d0894d26b9f_732x321.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xfz0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0c6600-1d59-4e30-ab5a-6d0894d26b9f_732x321.png 424w, https://substackcdn.com/image/fetch/$s_!xfz0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0c6600-1d59-4e30-ab5a-6d0894d26b9f_732x321.png 848w, https://substackcdn.com/image/fetch/$s_!xfz0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0c6600-1d59-4e30-ab5a-6d0894d26b9f_732x321.png 1272w, https://substackcdn.com/image/fetch/$s_!xfz0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0c6600-1d59-4e30-ab5a-6d0894d26b9f_732x321.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xfz0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0c6600-1d59-4e30-ab5a-6d0894d26b9f_732x321.png" width="732" height="321" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bb0c6600-1d59-4e30-ab5a-6d0894d26b9f_732x321.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:321,&quot;width&quot;:732,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!xfz0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0c6600-1d59-4e30-ab5a-6d0894d26b9f_732x321.png 424w, https://substackcdn.com/image/fetch/$s_!xfz0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0c6600-1d59-4e30-ab5a-6d0894d26b9f_732x321.png 848w, https://substackcdn.com/image/fetch/$s_!xfz0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0c6600-1d59-4e30-ab5a-6d0894d26b9f_732x321.png 1272w, https://substackcdn.com/image/fetch/$s_!xfz0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb0c6600-1d59-4e30-ab5a-6d0894d26b9f_732x321.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>For web developers, this is closer to:</p><ul><li><p>API discovery combined with schema introspection</p></li><li><p>Contract negotiation before execution</p></li><li><p>Runtime awareness instead of static assumptions</p></li></ul><p>The difference is that this model is designed for AI clients that interpret intent rather than strictly follow instructions.</p><h3><strong>Why This Matters in Practice</strong></h3><p>The biggest problem MCP addresses is not performance or scale. It is <strong>integration friction</strong>.</p><p>Without a standard:</p><ul><li><p>Each AI integration defines its own schema</p></li><li><p>Tool selection becomes unreliable</p></li><li><p>Context handling becomes inconsistent</p></li><li><p>Systems become harder to compose</p></li></ul><p>The source material highlights three recurring pain points:</p><ul><li><p>Fragmented context and limited windows</p></li><li><p>Tool and memory integration complexity</p></li><li><p>Lack of composability across domains</p></li></ul><p>MCP tackles these by standardizing how capabilities are described and invoked. For web developers, this is similar to the role OpenAPI played for REST. It does not replace APIs. It makes them easier to integrate and reason about.</p><h3><strong>The Real Design Challenge: Clarity Over Cleverness</strong></h3><p>One of the most practical insights from the material is how much <strong>naming and structure influence behavior</strong>.</p><p>In MCP systems:</p><ul><li><p>Tool descriptions guide selection</p></li><li><p>Parameter names influence argument extraction</p></li><li><p>Return shapes affect how results are used</p></li></ul><p>Vague naming leads to incorrect tool calls. Overloaded schemas introduce ambiguity. Overly complex resources increase cost and reduce accuracy.</p><p>This is not new, but the consequences are sharper.</p><p>In traditional APIs, poor naming slows developers down. In AI-driven systems, it changes how the system behaves.</p><p>That forces a shift toward:</p><ul><li><p>Clear, literal naming</p></li><li><p>Minimal and explicit schemas</p></li><li><p>Stable, predictable outputs</p></li></ul><p>This is API design discipline applied in a stricter environment.</p><h3><strong>Transport, Deployment, and the Web Stack</strong></h3><p>Another reason this matters for web developers is where these systems end up.</p><p>Local development may start with simple transports, but production systems move toward HTTP-based communication, aligning with existing infrastructure.</p><p>That brings familiar concerns back into play:</p><ul><li><p>Routing and endpoints</p></li><li><p>Authentication and token validation</p></li><li><p>Rate limiting and gateway policies</p></li><li><p>Observability and request tracing</p></li></ul><p>The recommendation to move toward a single HTTP endpoint for MCP traffic reflects a clear alignment with modern backend practices.</p><p>It is an extension of the web stack and not just parallel ecosystem.</p><h3><strong>Authentication Is No Longer Per Request</strong></h3><p>One subtle but important shift is how authentication is handled.</p><p>Instead of validating each request independently, MCP systems often establish trust at the connection or session level, with tokens validated before interaction begins.</p><p>That changes how you think about:</p><ul><li><p>Access control</p></li><li><p>Role mapping</p></li><li><p>Scope enforcement</p></li></ul><p>It also pushes developers to consider:</p><ul><li><p>Which tools should be publicly accessible</p></li><li><p>Which require elevated permissions</p></li><li><p>How to isolate sensitive operations</p></li></ul><p>This is closer to service-level authorization than traditional request-level checks.</p><h3><strong>From Local Tooling to Production Systems</strong></h3><p>One of the strengths of the MCP approach is how it spans environments. The same server can:</p><ul><li><p>Run locally for testing</p></li><li><p>Be inspected through development tools</p></li><li><p>Be integrated into host environments</p></li><li><p>Be deployed over HTTP for production use</p></li></ul><p>This continuity reduces the gap between experimentation and deployment.</p><p>For web developers, that means fewer environment-specific rewrites, easier validation workflows, and more predictable rollout paths</p><p>It also makes it easier to introduce AI-driven capabilities incrementally instead of rewriting entire systems.</p><h3><strong>Where MCP Fits in a Web Developer&#8217;s Mental Model</strong></h3><p>It helps to place MCP alongside existing concepts rather than treating it as something entirely new.</p><p>Think of it as:</p><ul><li><p>An extension of API design for AI-native clients</p></li><li><p>A structured way to expose backend capabilities</p></li><li><p>A protocol for discovery, not just execution</p></li></ul><p>It does not replace REST or GraphQL. It complements them by sitting one layer above, where interpretation and routing happen.</p><p>That positioning makes it easier to adopt without overhauling your architecture.</p><h3><strong>Key Takeaways</strong></h3><ul><li><p>MCP reframes backend design from static endpoints to discoverable capabilities</p></li><li><p>Tools, resources, and prompts map cleanly to actions, context, and reusable logic</p></li><li><p>Clear naming and schema design directly influence system behavior</p></li><li><p>HTTP-based deployment keeps MCP aligned with existing web infrastructure</p></li><li><p>Authentication shifts toward session-level trust and scoped permissions</p></li><li><p>The protocol reduces integration friction by standardizing how capabilities are exposed</p></li></ul><p>MCP is still early, but the direction is clear. AI clients are becoming another consumer of backend systems, and they require more than just endpoints.</p><p>For web developers, this is less about learning a new tool and more about recognizing a familiar pattern evolving into something more dynamic.</p><p>If you want to explore these ideas in more depth, check out<strong> </strong><em><strong><a href="https://www.amazon.com/Ship-MCP-Server-Python-production-ready-ebook/dp/B0GSZD6H2J/ref=sr_1_1">Ship an MCP Server in Python FAST</a></strong></em> by Christoffer Noring.</p><div><hr></div><h1 style="text-align: center;"><strong>Building with AI? We want to hear from you &#128064;</strong></h1><p><em><strong><a href="https://forms.gle/mbPP3uPsGzNnw29j7">Take our quick survey</a></strong></em> and help us shape content around real workflow bottlenecks.</p><p><strong><a href="https://forms.gle/mbPP3uPsGzNnw29j7">Take the survey</a></strong></p><div><hr></div><h1 style="text-align: center;"><strong>This Week in the News</strong></h1><ul><li><p><strong>&#9883;&#65039; <a href="https://tanstack.com/blog/react-server-components">TanStack Start adds experimental React Server Components support</a></strong>: <a href="https://tanstack.com/start/latest">TanStack Start</a> now includes experimental support for React Server Components (RSC), bringing server-first patterns into its full-stack React framework. It&#8217;s another sign that RSC is slowly moving from theory into real-world tooling.</p></li><li><p><strong>&#129302; <a href="https://code.claude.com/docs/en/routines">Claude introduces &#8220;routines&#8221; for repeatable workflows</a></strong>: Claude now supports <em>routines</em>, a way to define repeatable workflows for common tasks. Instead of prompting from scratch each time, developers can structure and reuse sequences, making interactions more consistent and efficient.</p></li><li><p><strong>&#127912; <a href="https://www.brycewray.com/posts/2026/04/hugos-new-css-powers/">Hugo adds new CSS capabilities</a>: </strong>Hugo&#8217;s latest updates introduce new CSS-related capabilities, expanding how styles can be handled within the static site generator. The changes aim to simplify styling workflows and give developers more flexibility when working with modern CSS setups.</p></li><li><p><strong>&#129513; <a href="https://github.github.com/gh-stack/">GitHub introduces stacked PRs in private preview</a></strong>: GitHub has opened a private preview for stacked pull requests, adding native support for workflows where large changes are split into a chain of dependent PRs. This approach can make reviews more manageable and help teams ship complex features incrementally.</p></li></ul><h1 style="text-align: center;"><strong>Beyond the Headlines</strong></h1><ul><li><p><strong>&#127912; <a href="https://nerdy.dev/why-ai-sucks-at-front-end">Why AI still struggles with frontend development</a></strong>: While AI tools are getting better at generating code, frontend development remains a weak spot. This piece breaks down where things fall apart, especially around layout, styling, and the nuanced decisions that go into building good user interfaces. The bigger takeaway is that frontend work isn&#8217;t just about producing code. It involves visual judgment, edge cases, and context that are still hard for AI systems to consistently handle.</p></li><li><p><strong>&#127959;&#65039; <a href="https://tkdodo.eu/blog/the-vertical-codebase">Rethinking architecture with the vertical codebase</a></strong>: This article explores the idea of a &#8220;vertical codebase,&#8221; where features are organized end-to-end instead of being split across layers like components, services, and utilities. The approach focuses on grouping everything related to a feature in one place, making codebases easier to navigate and reason about. It&#8217;s a shift from traditional horizontal layering toward a structure that prioritizes ownership, clarity, and maintainability as applications grow.</p></li><li><p><strong>&#129529;<a href="https://neciudan.dev/master-eslint-rules"> Mastering ESLint rules for better code quality</a>: </strong>This guide takes a deeper look at how to effectively use ESLint rules beyond basic setups. It focuses on understanding, customizing, and applying rules in a way that actually improves code quality instead of just adding noise. The key idea is that linting works best when it reflects team conventions and real-world usage, not just default configurations.</p></li><li><p><strong>&#128230; <a href="https://blog.whatwg.org/js-modules">Ten years of JavaScript modules on the web</a></strong>: It&#8217;s been ten years since the initial push to bring native JavaScript modules to the web platform. This retrospective looks at how far the ecosystem has come, from early proposals to widespread adoption across browsers and tooling. It&#8217;s a reminder of how foundational features evolve slowly, but end up reshaping how we structure and ship web applications.</p></li><li><p><strong>&#127908; <a href="https://www.igalia.com/chats/npmxyz">Inside npmx, a new way to explore the npm ecosystem</a>: </strong>This 50-minute conversation with the developers behind <strong><a href="https://npmx.dev/">npmx</a></strong> dives into the thinking behind a new way to browse and interact with the npm registry. The project is gaining traction as an alternative approach to discovering and working with packages. It offers a closer look at how tooling around npm is evolving beyond installation into better exploration and developer workflows.</p></li></ul><h1 style="text-align: center;"><strong><a href="https://www.eventbrite.co.uk/e/hands-on-spec-driven-development-workshop-cohort-2-tickets-1985498625838?aff=webdevpro">Stop Prompting. Start Speccing.</a></strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!aYXj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe597e801-090b-4c8e-a90e-ede8b0f8238e_800x400.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!aYXj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe597e801-090b-4c8e-a90e-ede8b0f8238e_800x400.jpeg 424w, https://substackcdn.com/image/fetch/$s_!aYXj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe597e801-090b-4c8e-a90e-ede8b0f8238e_800x400.jpeg 848w, https://substackcdn.com/image/fetch/$s_!aYXj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe597e801-090b-4c8e-a90e-ede8b0f8238e_800x400.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!aYXj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe597e801-090b-4c8e-a90e-ede8b0f8238e_800x400.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!aYXj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe597e801-090b-4c8e-a90e-ede8b0f8238e_800x400.jpeg" width="800" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e597e801-090b-4c8e-a90e-ede8b0f8238e_800x400.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!aYXj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe597e801-090b-4c8e-a90e-ede8b0f8238e_800x400.jpeg 424w, https://substackcdn.com/image/fetch/$s_!aYXj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe597e801-090b-4c8e-a90e-ede8b0f8238e_800x400.jpeg 848w, https://substackcdn.com/image/fetch/$s_!aYXj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe597e801-090b-4c8e-a90e-ede8b0f8238e_800x400.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!aYXj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe597e801-090b-4c8e-a90e-ede8b0f8238e_800x400.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></figure></div><p>After a hugely successful Cohort 1, we&#8217;re back with the Cohort 2 hands-on workshop!</p><p>Here you&#8217;ll build a real full-stack application using the same spec-first methodology used by MAANG engineering teams.</p><p><strong><a href="https://www.eventbrite.co.uk/e/hands-on-spec-driven-development-workshop-cohort-2-tickets-1985498625838?aff=webdevpro">20 early bird seats at 40% off. Use code NL40</a></strong></p><h1 style="text-align: center;"><strong>Tool of the Week</strong></h1><p><strong>&#127912; <a href="https://lokeshdhakar.com/projects/color-thief/">Extract color palettes directly from images</a></strong></p><p>Choosing the right color palette can be tricky, especially when working with images. <strong><a href="https://lokeshdhakar.com/projects/color-thief/">Color Thief</a></strong> makes it simple by extracting dominant colors and palettes directly from images using a lightweight JavaScript library.</p><p>It&#8217;s especially useful for building dynamic UIs, theming applications, or generating color schemes based on user content.</p><p><em>That&#8217;s all for this week. Have any ideas you want to see in the next article? Hit Reply!</em></p><p>Cheers!</p><p>Editor-in-chief,</p><p>Kinnari Chohan </p><div><hr></div><p><strong>&#128075; <a href="https://landing.packtpub.com/sponsorship-landing-page/">Advertise with us</a></strong><br><strong> </strong>Interested in sponsoring this newsletter and reaching a highly engaged audience of tech professionals? Simply reply to this email, and our team will get in touch with the next steps.</p>]]></content:encoded></item><item><title><![CDATA[WebDevPro #134: Rendering in Next.js is a system of trade-offs, not a feature checklist]]></title><description><![CDATA[Crafting the Web: Tips, Tools, and Trends for Developers]]></description><link>https://packtwebdevpro.substack.com/p/webdevpro-134-rendering-in-nextjs</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/webdevpro-134-rendering-in-nextjs</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Mon, 13 Apr 2026 14:03:52 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!yfWF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b9bfe15-9104-49d5-9161-b8d2844c8f6c_800x400.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 style="text-align: center;"><strong><a href="https://insertaffiliate.com/">Grow your mobile apps efficiently, without ads!</a></strong></h1><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vg9q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f21d82b-eb6c-40e1-9af7-0c2de1ddaf86_250x95.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vg9q!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f21d82b-eb6c-40e1-9af7-0c2de1ddaf86_250x95.png 424w, https://substackcdn.com/image/fetch/$s_!vg9q!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f21d82b-eb6c-40e1-9af7-0c2de1ddaf86_250x95.png 848w, https://substackcdn.com/image/fetch/$s_!vg9q!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f21d82b-eb6c-40e1-9af7-0c2de1ddaf86_250x95.png 1272w, https://substackcdn.com/image/fetch/$s_!vg9q!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f21d82b-eb6c-40e1-9af7-0c2de1ddaf86_250x95.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vg9q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f21d82b-eb6c-40e1-9af7-0c2de1ddaf86_250x95.png" width="250" height="95" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9f21d82b-eb6c-40e1-9af7-0c2de1ddaf86_250x95.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:95,&quot;width&quot;:250,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!vg9q!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f21d82b-eb6c-40e1-9af7-0c2de1ddaf86_250x95.png 424w, https://substackcdn.com/image/fetch/$s_!vg9q!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f21d82b-eb6c-40e1-9af7-0c2de1ddaf86_250x95.png 848w, https://substackcdn.com/image/fetch/$s_!vg9q!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f21d82b-eb6c-40e1-9af7-0c2de1ddaf86_250x95.png 1272w, https://substackcdn.com/image/fetch/$s_!vg9q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f21d82b-eb6c-40e1-9af7-0c2de1ddaf86_250x95.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p><em>Do you rely on paid ads for mobile growth? Don&#8217;t the rising costs and limited visibility make it harder to scale?</em><br><br><strong>Insert Affiliate gives you another option.</strong><br>It lets you run an affiliate channel for your app, where partners, creators, or communities drive users via tracked links, and you can tie installs, purchases, and subscriptions back to the source.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://insertaffiliate.com/&quot;,&quot;text&quot;:&quot;Start tracking affiliate revenue&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://insertaffiliate.com/"><span>Start tracking affiliate revenue</span></a></p><div><hr></div><p>Welcome to this week&#8217;s issue of WebDevPro!</p><p>Most of us think rendering strategies were a matter of picking the &#8220;best&#8221; option.</p><p>Server-side rendering felt powerful. Static generation felt fast. Client-side rendering felt flexible. The assumption was simple: choose one, commit, and move on.</p><p>That mental model breaks down the moment your application grows beyond a few pages.</p><p>In practice, rendering is not a decision you make once. It is a system of trade-offs you keep revisiting as your product evolves. Next.js does not force you into one approach. It gives you multiple levers and expects you to use them deliberately.</p><p>The real shift is not technical. It is conceptual. You stop asking &#8220;Which rendering strategy should I use?&#8221; and start asking &#8220;Where should this piece of UI live, and when should it be rendered?&#8221;</p><p>Before we get into it, here&#8217;s this week at a glance:</p><ul><li><p><em><strong>&#129504; <a href="https://github.blog/ai-and-ml/github-copilot/github-copilot-cli-combines-model-families-for-a-second-opinion">Copilot now asks another AI before trusting itself</a></strong></em></p></li><li><p><em><strong>&#128272; <a href="https://blog.cloudflare.com/post-quantum-roadmap">Cloudflare just moved up the deadline for quantum-safe internet</a></strong></em></p></li><li><p><em><strong>&#9881;&#65039; <a href="https://nodejs.org/en/blog/release/">Node.js keeps shipping under-the-radar improvements</a></strong></em></p></li><li><p><em><strong>&#9888;&#65039; <a href="https://simonwillison.net/2026/Apr/3/supply-chain-social-engineering/">How attackers are now targeting open source maintainers</a></strong></em></p></li><li><p><em><strong>&#129513; <a href="https://www.hollandtech.net/claude-is-not-your-architect/">Claude is not your software architect</a></strong></em></p></li><li><p><em><strong>&#127909; <a href="https://www.youtube.com/watch?v=PXq6awYzfT8">The React hook most developers still ignore</a></strong></em></p></li></ul><h3><strong>The illusion of a single rendering strategy</strong></h3><p>Traditional frameworks leaned heavily in one direction.</p><p>Server-rendered apps generated HTML on every request. Client-rendered apps shipped a JavaScript bundle and built everything in the browser. Static site generators pushed everything to build time. Each model worked well in isolation. Each also came with blind spots.</p><p>Next.js breaks that boundary. You can render some pages at request time, others at build time, and still defer specific components to the client. This flexibility is powerful, but it also introduces a new responsibility: understanding the cost of each choice.</p><p>Rendering is no longer about capability. It is about trade-offs across performance, scalability, user experience, and operational complexity.</p><h3><strong>Server-side rendering is about control, not just freshness</strong></h3><p>Server-side rendering still plays a critical role, especially when the content depends on the request itself.</p><p>When a page is rendered on the server for every request, you gain control over what gets sent to the browser. You can safely access private APIs, validate data, and tailor responses per user. The browser receives fully formed HTML, which improves compatibility and helps search engines understand your content immediately. That control comes at a cost.</p><p>Every request triggers computation. Every data dependency introduces latency. Even a well-optimized server will feel slower compared to serving a prebuilt file. Navigation between pages can feel heavier because each transition depends on server work.</p><p>There is also an operational dimension. A server-rendered app is not just code. It is infrastructure. It scales with traffic, and that scaling has a cost.</p><p>SSR shines when you genuinely need per-request freshness or personalization. It becomes a liability when used out of habit.</p><p>A common mistake is defaulting to SSR for anything that &#8220;feels dynamic.&#8221; In reality, many of those pages do not need to be recomputed on every request. They only need to feel dynamic.</p><h3><strong>Client-side rendering shifts responsibility to the browser</strong></h3><p>Client-side rendering takes the opposite approach. Instead of sending meaningful HTML, the server delivers a minimal shell and a JavaScript bundle. The browser then builds the interface, fetches data, and manages state.</p><p>This model feels fast after the initial load. Once the application is hydrated, navigation becomes seamless. Transitions are smooth. Interactions feel immediate. The app behaves more like a native experience. There is a reason this approach became popular.</p><p>It reduces server workload significantly. The server becomes a delivery mechanism rather than a computation layer. You can scale more easily, especially in serverless environments. You also gain flexibility in how and when you fetch data.</p><p>But the trade-offs are hard to ignore. The first load can be painfully slow on weak networks. Users may stare at an empty screen while JavaScript downloads and executes. Search engines see very little initial content, which can impact discoverability and performance scores .</p><p>Client-side rendering works well when SEO is not a priority and when interactivity outweighs initial load performance. Think dashboards, internal tools, or authenticated user spaces.</p><p>Even then, it should be a deliberate choice, not a default fallback.</p><h3><strong>Static generation optimizes for speed and scale</strong></h3><p>Static site generation flips the model again. Instead of rendering on the server per request or in the browser at runtime, you render at build time. The output is a static HTML file that can be served instantly.</p><p>This approach is hard to beat in terms of performance. There is no computation at request time. The server simply returns a file. CDNs cache and distribute it globally. Latency drops dramatically. Scalability becomes almost trivial .</p><p>It is also inherently secure. There are no runtime calls to sensitive APIs. No database queries during requests. Everything needed is already embedded in the generated output.</p><p>The limitation is obvious. Static content does not change unless you rebuild. That constraint used to make static generation impractical for dynamic applications. Rebuilding an entire site for a small content change is inefficient and often unrealistic. Next.js softens that limitation through incremental static regeneration.</p><h3><strong>Incremental regeneration changes the conversation</strong></h3><p>Incremental static regeneration introduces a middle ground. You can generate a page once and then update it periodically without rebuilding the entire application. Instead of choosing between fully static and fully dynamic, you define how stale your data can be.</p><p>A page might be regenerated every few minutes, hours, or based on traffic patterns. The first request after the revalidation window triggers a new render, and subsequent users receive the updated version .</p><p>This model shifts the question from &#8220;Is this page static or dynamic?&#8221; to &#8220;How fresh does this data need to be?&#8221;</p><p>Many applications do not require real-time updates. A slight delay is acceptable if it significantly improves performance and reduces load. ISR lets you capture that balance without overcommitting to server-side rendering.</p><h3><strong>Rendering decisions are architectural decisions</strong></h3><p>At an intermediate level, the real challenge is not understanding how each strategy works. It is knowing where to apply them.</p><p>Rendering is tightly coupled with architecture. A marketing page benefits from static generation because it rarely changes and needs to load instantly. A product listing page might use a mix of static generation and periodic revalidation. A user dashboard leans toward client-side rendering for responsiveness. A checkout flow may rely on server-side rendering for security and consistency.</p><p>These are not isolated decisions. They influence data flow, caching strategies, and even how teams structure their codebase. Rendering becomes part of the system design, not just a framework feature.</p><h3><strong>The hidden cost of getting it wrong</strong></h3><p>Misusing rendering strategies can degrade your application. Overusing server-side rendering can lead to unnecessary latency and higher infrastructure costs. The app works, but it feels slower than it should.</p><p>Relying too heavily on client-side rendering can hurt first impressions. Users wait longer. Search engines struggle to index content. Performance scores drop. Using static generation without a plan for updates can create stale experiences. Content lags behind reality. Users notice.</p><p>The tricky part is that each of these issues emerges gradually. They rarely show up in small projects or local environments. They appear under real traffic, real data, and real user expectations. That is why rendering decisions deserve more attention than they usually get.</p><h3><strong>Hybrid rendering is not a feature but a mindset</strong></h3><p>Next.js is often described as a hybrid framework. That description is accurate but incomplete.</p><p>A single page can combine multiple approaches. The shell might be statically generated. Critical data might be fetched on the server. Interactive components might rely on client-side rendering.</p><p>Each part of the page is treated independently based on its requirements. This is where the framework becomes powerful. You are not forced into a single pattern. You can optimize each piece of the experience.</p><p>The challenge is maintaining clarity. Without clear boundaries, hybrid approaches can become messy. It is easy to lose track of where data is fetched, where rendering happens, and why certain decisions were made.</p><h3><strong>What developers often miss</strong></h3><p>At this stage, most developers understand the mechanics of SSR, CSR, and SSG. The gap is usually in decision-making.</p><p>Three patterns tend to show up repeatedly.</p><ul><li><p>The first is defaulting to server-side rendering for anything dynamic. It feels safe, but it often introduces unnecessary overhead.</p></li><li><p>The second is treating client-side rendering as a performance solution. It improves interactions but can hurt initial load and SEO.</p></li><li><p>The third is underestimating static generation. Many pages that could be static end up being rendered dynamically simply because it feels easier.</p></li></ul><p>These patterns become problematic when applied without context.</p><h3><strong>A more practical way to think about rendering</strong></h3><p>Instead of categorizing pages by rendering type, it helps to evaluate them through a few simple questions:</p><ul><li><p>How often does this data change?</p></li><li><p>Does this content need to be indexed by search engines?</p></li><li><p>How important is initial load performance?</p></li><li><p>Does this page require per-user personalization?</p></li><li><p>What is the acceptable level of staleness?</p></li></ul><p>These questions lead you toward a more balanced approach.</p><p>A page that rarely changes and needs strong SEO leans toward static generation. A page with user-specific data leans toward server or client rendering. A page with moderate updates fits well with incremental regeneration.</p><p>Rendering stops being a technical choice and becomes a product decision.</p><h3><strong>The real takeaway</strong></h3><p>Rendering strategies are not competing features. They are tools with different costs and benefits.</p><p>Next.js gives you the ability to combine them, but it does not make the decisions for you. That responsibility sits with the developer.</p><p>When you align your rendering choices with the needs of your application, performance improves, infrastructure becomes more efficient, and the user experience feels intentional.</p><p>When you do not, the issues show up slowly and compound over time. Rendering is one of those areas where small decisions have outsized impact. It is worth treating it as a first-class concern, not an afterthought.</p><p>Enjoyed this piece? Take it further with <em><strong><a href="https://www.amazon.com/Real-World-Next-js-high-performance-applications-production/dp/180107349X/ref=sr_1_1">Real-World Next.js</a></strong></em> by Michele Riva, and learn how to build scalable, high-performance modern web applications.</p><div><hr></div><p><strong>Building with AI? We want to hear from you &#128064;</strong><br><em><strong><a href="https://forms.gle/mbPP3uPsGzNnw29j7">Take our quick survey</a></strong></em> and help us shape content around real workflow bottlenecks.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://docs.google.com/forms/d/e/1FAIpQLSd30w6yvGtzwx8gzhaz-mXHS8YajaDkej2Gj6Pi3h_nsSiOTA/viewform&quot;,&quot;text&quot;:&quot;Take the survey&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://docs.google.com/forms/d/e/1FAIpQLSd30w6yvGtzwx8gzhaz-mXHS8YajaDkej2Gj6Pi3h_nsSiOTA/viewform"><span>Take the survey</span></a></p><div><hr></div><h1 style="text-align: center;"><strong>This Week in the News</strong></h1><ul><li><p>&#129504; <strong><a href="https://github.blog/ai-and-ml/github-copilot/github-copilot-cli-combines-model-families-for-a-second-opinion">Copilot now asks another AI before trusting itself</a></strong>: GitHub is experimenting with a &#8220;second opinion&#8221; system inside Copilot CLI. A separate model from a different family reviews the agent&#8217;s plan and code to catch blind spots and edge cases before execution. The bigger shift is architectural. AI tools are starting to validate each other, not just generate output. One model writes, another critiques, and the developer sits above both.</p></li><li><p>&#128272; <strong><a href="https://blog.cloudflare.com/post-quantum-roadmap">Cloudflare just moved up the deadline for quantum-safe internet</a></strong>: Cloudflare is accelerating its roadmap to make the entire platform post-quantum secure by 2029, including authentication, not just encryption. The urgency comes from recent breakthroughs suggesting current cryptography could be broken sooner than expected. The takeaway is simple. Quantum risk is no longer theoretical, and migration timelines are shrinking fast.</p></li><li><p>&#9881;&#65039; <strong><a href="https://nodejs.org/en/blog/release/">Node.js keeps shipping under-the-radar improvements</a>: </strong>Recent updates to the current release line focus on better memory control, improved test runner capabilities, and incremental API enhancements. Nothing headline grabbing, but that is the point. Node is doubling down on stability and developer ergonomics rather than chasing trends.</p></li><li><p>&#128230; <strong><a href="https://www.youtube.com/watch?v=xPJkoJ6dlqE">A new way to explore npm without the CLI</a></strong>: Patak and Zeu introduced <strong>npmx</strong>, a fast, browser-based interface for exploring the npm ecosystem. It focuses on speed, discoverability, and a cleaner way to navigate packages without relying on terminal workflows. The idea is simple but interesting. As ecosystems grow, developer tooling is shifting from command-heavy interfaces to faster, more visual ways of understanding what&#8217;s out there.</p></li></ul><h1 style="text-align: center;"><strong>Beyond the Headlines</strong></h1><ul><li><p>&#9888;&#65039; <strong><a href="https://simonwillison.net/2026/Apr/3/supply-chain-social-engineering/">How attackers are now targeting open source maintainers</a></strong>: Simon Willison breaks down a new wave of supply chain attacks that rely on social engineering, not exploits. Maintainers are being manipulated into merging malicious code through trust, urgency, and subtle persuasion. The pattern is uncomfortable but clear. The weakest point in the supply chain is no longer code. It is the human reviewing it.</p></li><li><p>&#129513; <strong><a href="https://www.hollandtech.net/claude-is-not-your-architect/">Claude is not your software architect</a></strong>: This piece challenges a growing assumption that AI can design systems end-to-end. While models can generate code and suggest structures, they lack the context needed for real architectural decisions. The distinction matters. AI can assist implementation, but architecture still depends on trade-offs, constraints, and long-term thinking.</p></li><li><p>&#128272; <strong><a href="https://spencermortensen.com/articles/email-obfuscation/">Your email is still easy to scrape</a></strong><a href="https://trigger.dev/blog/firebun">: </a>Email obfuscation techniques that used to work are now trivial to bypass. This article shows how bots extract addresses even from &#8220;protected&#8221; formats and what actually works today. The takeaway is practical. Security through obscurity is fading fast, especially when automation keeps improving.</p></li><li><p>&#127909; <strong><a href="https://www.youtube.com/watch?v=PXq6awYzfT8">The React hook most developers still ignore</a></strong>: <em>useSyncExternalStore</em> solves a specific but important problem: syncing external state with React without breaking consistency. It rarely shows up in everyday code, which is why many developers overlook it. But once you start working with shared state across systems, it becomes one of those tools that quietly fixes hard-to-debug issues.</p><div><hr></div></li></ul><h1 style="text-align: center;"><strong><a href="https://www.eventbrite.co.uk/e/hands-on-spec-driven-development-workshop-cohort-2-tickets-1985498625838?aff=webdevpro">Stop Prompting. Start Speccing.</a></strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!yfWF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b9bfe15-9104-49d5-9161-b8d2844c8f6c_800x400.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yfWF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b9bfe15-9104-49d5-9161-b8d2844c8f6c_800x400.jpeg 424w, https://substackcdn.com/image/fetch/$s_!yfWF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b9bfe15-9104-49d5-9161-b8d2844c8f6c_800x400.jpeg 848w, https://substackcdn.com/image/fetch/$s_!yfWF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b9bfe15-9104-49d5-9161-b8d2844c8f6c_800x400.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!yfWF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b9bfe15-9104-49d5-9161-b8d2844c8f6c_800x400.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yfWF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b9bfe15-9104-49d5-9161-b8d2844c8f6c_800x400.jpeg" width="800" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8b9bfe15-9104-49d5-9161-b8d2844c8f6c_800x400.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!yfWF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b9bfe15-9104-49d5-9161-b8d2844c8f6c_800x400.jpeg 424w, https://substackcdn.com/image/fetch/$s_!yfWF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b9bfe15-9104-49d5-9161-b8d2844c8f6c_800x400.jpeg 848w, https://substackcdn.com/image/fetch/$s_!yfWF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b9bfe15-9104-49d5-9161-b8d2844c8f6c_800x400.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!yfWF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b9bfe15-9104-49d5-9161-b8d2844c8f6c_800x400.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></figure></div><p>After a hugely successful Cohort 1, we&#8217;re back with the Cohort 2 hands-on workshop!</p><p>Here you&#8217;ll build a real full-stack application using the same spec-first methodology used by MAANG engineering teams.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.eventbrite.co.uk/e/hands-on-spec-driven-development-workshop-cohort-2-tickets-1985498625838?aff=webdevpro&quot;,&quot;text&quot;:&quot;Get 40% off. Use code NL40&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.eventbrite.co.uk/e/hands-on-spec-driven-development-workshop-cohort-2-tickets-1985498625838?aff=webdevpro"><span>Get 40% off. Use code NL40</span></a></p><div><hr></div><h1 style="text-align: center;"><strong>Tool of the Week</strong></h1><p>&#129460; <strong><a href="https://github.com/0xGF/boneyard">Generate skeleton screens directly from your DOM</a></strong></p><p>Boneyard takes a snapshot of your existing DOM and automatically generates pixel-perfect skeleton screens. Instead of manually building placeholders, it mirrors your actual layout, saving time and keeping loading states visually consistent.</p><p>It&#8217;s a small idea with a practical payoff, especially for apps where perceived performance matters as much as real speed.</p><p><em>That&#8217;s all for this week. Have any ideas you want to see in the next article? Hit Reply!</em></p><p>Cheers!</p><p>Editor-in-chief,</p><p>Kinnari Chohan</p><div><hr></div><p><strong>&#128075; <a href="https://landing.packtpub.com/sponsorship-landing-page/">Advertise with us</a></strong><br><strong> </strong>Interested in sponsoring this newsletter and reaching a highly engaged audience of tech professionals? Simply reply to this email, and our team will get in touch with the next steps.</p>]]></content:encoded></item><item><title><![CDATA[WebDevPro #133: Rethinking Backend Communication for Real-Time Systems]]></title><description><![CDATA[Crafting the Web: Tips, Tools, and Trends for Developers]]></description><link>https://packtwebdevpro.substack.com/p/webdevpro-133-rethinking-backend</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/webdevpro-133-rethinking-backend</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Mon, 06 Apr 2026 14:03:35 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!cXlf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11a94e58-6ada-4b8b-93bc-d7b30c86ea03_800x400.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cXlf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11a94e58-6ada-4b8b-93bc-d7b30c86ea03_800x400.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cXlf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11a94e58-6ada-4b8b-93bc-d7b30c86ea03_800x400.png 424w, https://substackcdn.com/image/fetch/$s_!cXlf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11a94e58-6ada-4b8b-93bc-d7b30c86ea03_800x400.png 848w, https://substackcdn.com/image/fetch/$s_!cXlf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11a94e58-6ada-4b8b-93bc-d7b30c86ea03_800x400.png 1272w, https://substackcdn.com/image/fetch/$s_!cXlf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11a94e58-6ada-4b8b-93bc-d7b30c86ea03_800x400.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cXlf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11a94e58-6ada-4b8b-93bc-d7b30c86ea03_800x400.png" width="800" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/11a94e58-6ada-4b8b-93bc-d7b30c86ea03_800x400.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!cXlf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11a94e58-6ada-4b8b-93bc-d7b30c86ea03_800x400.png 424w, https://substackcdn.com/image/fetch/$s_!cXlf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11a94e58-6ada-4b8b-93bc-d7b30c86ea03_800x400.png 848w, https://substackcdn.com/image/fetch/$s_!cXlf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11a94e58-6ada-4b8b-93bc-d7b30c86ea03_800x400.png 1272w, https://substackcdn.com/image/fetch/$s_!cXlf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11a94e58-6ada-4b8b-93bc-d7b30c86ea03_800x400.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>Job postings at Microsoft, Deloitte, Accenture, and KPMG are now listing Copilot Studio, Power Automate, and MCP as must-have skills. The fastest way to get there?</p><p><em><strong><a href="https://www.eventbrite.com/e/hands-on-agentic-ai-for-enterprise-transformation-tickets-1984601412248?aff=devpronl">Build a real enterprise AI agent in 2 days LIVE</a>, with instructors from Microsoft and Confluent.</strong></em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.eventbrite.co.uk/e/hands-on-agentic-ai-for-enterprise-transformation-tickets-1984601412248?aff=devpronl&quot;,&quot;text&quot;:&quot;Use SAVE40 for 40% off. Grab your spot!&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.eventbrite.co.uk/e/hands-on-agentic-ai-for-enterprise-transformation-tickets-1984601412248?aff=devpronl"><span>Use SAVE40 for 40% off. Grab your spot!</span></a></p><div><hr></div><p>Welcome to this week&#8217;s issue of WebDevPro!</p><p>Most backend systems are built around a simple assumption: the client asks, the server responds, and the connection ends. That model has worked for decades because it fits neatly with how the web evolved. It scales well, it&#8217;s easy to reason about, and most infrastructure is designed around it.</p><p>But the moment you step into real-time features, that assumption starts to break.</p><p>Chat apps, collaborative tools, live dashboards, multiplayer systems, and even notifications all share one requirement: <strong>the server needs to speak without being asked</strong>. That single shift changes how you design your backend, how you think about state, and how you handle communication altogether. This is where event-driven systems enter the picture.</p><p>Before we get into it, here&#8217;s this week at a glance:</p><ul><li><p>&#129302; <em><strong><a href="https://cursor.com/blog/cursor-3">Cursor 3 is built around an agent-first workflow</a></strong></em></p></li><li><p>&#9881;&#65039; <em><strong><a href="https://nextjs.org/blog/nextjs-across-platforms">Next.js moves beyond Vercel with a new Adapter API</a></strong></em></p></li><li><p>&#129302; <em><strong><a href="https://sentry.io/cookbook/">AI debugging shifts toward agent-driven workflows at Sentry</a></strong></em></p></li><li><p>&#9888;&#65039; <em><strong><a href="https://notes.zachmanson.com/copilot-edited-an-ad-into-my-pr/">Copilot incident highlights risks in AI-assisted coding</a></strong></em></p></li><li><p>&#9889; <em><strong><a href="https://trigger.dev/blog/firebun">Trigger.dev reports major performance gains after switching to Bun</a></strong></em></p></li><li><p>&#128230;<em> <strong><a href="https://wasp.sh/blog/2026/03/25/gentle-intro-npm-workspaces">npm workspaces finally make sense</a></strong></em></p></li></ul><h3><strong>Where Request-Response Falls Short</strong></h3><p>Consider a typical chat system built with REST:</p><ul><li><p>Fetch messages with GET /messages</p></li><li><p>Send messages with POST /messages</p></li><li><p>Poll regularly to check for updates</p></li></ul><p>Polling is the problem. You either:</p><ul><li><p>Poll frequently and waste resources, or</p></li><li><p>Poll less often and introduce lag</p></li></ul><p>Even long polling only stretches the same model. The client is still responsible for initiating communication.</p><p>Event-driven systems remove that constraint. Instead of asking repeatedly, the client stays connected and receives updates as they happen.</p><h3><strong>Persistent Connections Change the Rules</strong></h3><p>WebSockets make this possible by keeping a connection open between client and server. Both sides can send messages at any time.</p><p>This introduces three key shifts:</p><ul><li><p>Communication becomes bidirectional</p></li><li><p>The server can initiate updates</p></li><li><p>The connection now carries state</p></li></ul><p>That last point is the tradeoff. Stateless systems are easy to scale. Stateful connections require you to manage:</p><ul><li><p>Connection lifecycle</p></li><li><p>Reconnection</p></li><li><p>Failure handling</p></li></ul><p>You gain responsiveness, but complexity increases.</p><h3><strong>Why Abstractions Like Socket.IO Matter</strong></h3><p>WebSockets provide the foundation, but they are intentionally minimal. Production systems need more than just a raw connection.</p><p>Socket.IO adds:</p><ul><li><p>Automatic reconnection</p></li><li><p>Fallback to long polling</p></li><li><p>Event-based APIs</p></li><li><p>Broadcasting and grouping</p></li><li><p>Logical channels via rooms</p></li></ul><p>This shifts your backend from handling endpoints to handling events.</p><h3><strong>Thinking in Events Instead of Endpoints</strong></h3><p>In REST, you design routes and responses. In event-driven systems, you design interactions.</p><p>Instead of:</p><p><code>POST /messages<br>GET /messages</code></p><p>You work with:</p><p><code>socket.emit(&#8217;chat.message&#8217;, message)<br><br>socket.on(&#8217;chat.message&#8217;, (msg) =&gt; {<br>// handle message<br>})</code></p><p>The server becomes an event hub, and clients react to changes as they occur. This model aligns better with systems where state evolves continuously.</p><h3><strong>Broadcasting and Scope</strong></h3><p>A core capability of event-driven systems is broadcasting:</p><p><code>io.emit(&#8217;chat.message&#8217;, payload)</code></p><p>This allows one event to reach many clients instantly. But sending everything to everyone rarely works in practice. You need scope. Rooms provide that control:</p><p><code>socket.join(room)<br>io.to(room).emit(&#8217;chat.message&#8217;, payload)</code></p><p>This lets you:</p><ul><li><p>Segment users</p></li><li><p>Isolate conversations</p></li><li><p>Reduce unnecessary updates</p></li></ul><p>Rooms are not just a feature. They are how you model context in real-time systems.</p><h3><strong>When You Still Need Responses</strong></h3><p>Event-driven systems are asynchronous by default, but not everything fits that model. Sometimes you need a response, such as fetching user data or validating an action. Socket.IO supports this through acknowledgments:</p><p><code>const userInfo = await socket.emitWithAck(&#8217;user.info&#8217;, socket.id)</code></p><p>This creates a hybrid model where event-driven flows and request-response patterns coexist. In practice, most systems rely on both.</p><h3><strong>Authentication Becomes a Connection Concern</strong></h3><p>In REST, authentication happens per request. With persistent connections, it happens during the handshake:</p><p><code>io.use((socket, next) =&gt; {<br>// verify token<br>})</code></p><p>Once established, the connection is trusted. This introduces new questions:</p><p><em>What happens when tokens expire? How do you revoke access in real time? How do you store credentials securely?</em></p><p>Even token storage becomes more critical, as insecure storage mechanisms can expose credentials.</p><p>Authentication is no longer a repeated check. It becomes part of connection management.</p><h3><strong>The Tradeoff: State and Scaling</strong></h3><p>The biggest difference between REST and event-driven systems is state. REST systems are stateless, which makes scaling straightforward. Any server can handle any request. Event-driven systems maintain active connections. That means:</p><ul><li><p>Servers track clients</p></li><li><p>Messages must reach specific connections</p></li><li><p>Load balancing becomes more complex</p></li></ul><p>At scale, this often requires additional infrastructure like shared message layers or coordinated routing. This is where the simplicity of REST becomes hard to replace.</p><h3><strong>Choosing the Right Model</strong></h3><p>Event-driven systems are not a replacement for REST. They solve a different class of problems. They work best when:</p><ul><li><p>Data changes frequently</p></li><li><p>Users expect immediate updates</p></li><li><p>Interaction is continuous</p></li></ul><p>They add unnecessary complexity when:</p><ul><li><p>Data is mostly static</p></li><li><p>Caching is effective</p></li><li><p>Real-time behavior is not critical</p></li></ul><p>A blog platform benefits from REST. A collaborative editor does not. Instead of focusing on tools, focus on interaction patterns, ask:</p><p><em>Does the server need to push updates?</em></p><p><em>Do users depend on real-time feedback?</em></p><p><em>Is the system driven by events rather than requests?</em></p><p>If yes, an event-driven approach is worth the tradeoff.</p><h3><strong>Key Takeaways</strong></h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iUmw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F554bac69-b3b0-44ef-b6cb-4a9ef7e41e6e_716x791.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iUmw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F554bac69-b3b0-44ef-b6cb-4a9ef7e41e6e_716x791.png 424w, https://substackcdn.com/image/fetch/$s_!iUmw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F554bac69-b3b0-44ef-b6cb-4a9ef7e41e6e_716x791.png 848w, https://substackcdn.com/image/fetch/$s_!iUmw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F554bac69-b3b0-44ef-b6cb-4a9ef7e41e6e_716x791.png 1272w, https://substackcdn.com/image/fetch/$s_!iUmw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F554bac69-b3b0-44ef-b6cb-4a9ef7e41e6e_716x791.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iUmw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F554bac69-b3b0-44ef-b6cb-4a9ef7e41e6e_716x791.png" width="668" height="737.9720670391062" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/554bac69-b3b0-44ef-b6cb-4a9ef7e41e6e_716x791.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:791,&quot;width&quot;:716,&quot;resizeWidth&quot;:668,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!iUmw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F554bac69-b3b0-44ef-b6cb-4a9ef7e41e6e_716x791.png 424w, https://substackcdn.com/image/fetch/$s_!iUmw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F554bac69-b3b0-44ef-b6cb-4a9ef7e41e6e_716x791.png 848w, https://substackcdn.com/image/fetch/$s_!iUmw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F554bac69-b3b0-44ef-b6cb-4a9ef7e41e6e_716x791.png 1272w, https://substackcdn.com/image/fetch/$s_!iUmw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F554bac69-b3b0-44ef-b6cb-4a9ef7e41e6e_716x791.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>Real-time systems are less about adopting new tools and more about changing how you think about communication. Once the server is no longer passive, the entire shape of your backend begins to evolve.</p><p>If you want to explore how these concepts come together in a full application, <em><strong><a href="https://www.amazon.com/Modern-Full-Stack-React-Projects-maintain/dp/1837637954">Modern Full-Stack React Projects</a></strong></em> by Daniel Bugl is a solid next step.</p><h1 style="text-align: center;"><strong>This Week in the News</strong></h1><ul><li><p>&#129302; <strong><a href="https://cursor.com/blog/cursor-3">Cursor 3 introduces a unified workspace for coding with agents</a></strong>: Cursor 3 is a full redesign built around managing AI agents in one place. You can run multiple agents in parallel, move work between local and cloud, and go from generated changes to merged PRs without leaving the interface. The shift is not about replacing coding. It is about raising the level of abstraction. You spend less time juggling tools and more time coordinating how work gets done.</p></li><li><p>&#9881;&#65039; <strong><a href="https://nextjs.org/blog/nextjs-across-platforms">Next.js is finally decoupling from Vercel</a></strong>: Next.js is making a clear move toward platform independence. The new Adapter API creates a shared contract that lets any provider support Next.js reliably, backed by a public test suite and collaboration across Cloudflare, Netlify, AWS, and more. The direction is hard to miss. Next.js is no longer just a framework tied to one deployment model. It is becoming an infrastructure that can run anywhere without compromises.</p></li><li><p>&#128736;&#65039; <strong><a href="https://sentry.io/cookbook/">Sentry is turning debugging into agent workflows</a></strong>: Sentry&#8217;s new cookbook is a collection of ready-made &#8220;agent recipes&#8221; designed to help AI systems find, debug, and fix issues faster. Instead of treating observability as a dashboard, it becomes something agents can act on directly. The direction is clear. Debugging is no longer just about seeing errors. It&#8217;s about giving agents the context to resolve them automatically.</p></li><li><p>&#9888;&#65039; <strong><a href="https://notes.zachmanson.com/copilot-edited-an-ad-into-my-pr/">Copilot briefly inserted an ad into a pull request</a></strong>: A developer noticed Copilot had edited an unexpected &#8216;ad&#8217; into a PR, raising questions about how AI tools modify code. GitHub&#8217;s <a href="https://x.com/martinwoodward/status/2038612131084464521">Martin Woodward later clarified</a> what caused the behavior and confirmed the feature has now been disabled. It&#8217;s a small incident, but a reminder that AI-assisted coding still needs clear boundaries and visibility.</p></li><li><p>&#129513; <strong><a href="https://github.com/openai/codex-plugin-cc">Run Codex inside Claude Code</a></strong>: The Codex plugin brings OpenAI&#8217;s Codex directly into Claude Code, combining two AI systems into a single workflow. It allows developers to delegate tasks like code reviews and bug fixes to background jobs while continuing to work. The interesting shift here is orchestration. Instead of one assistant, developers are starting to coordinate multiple agents for different tasks.</p></li><li><p>&#9729;&#65039; <strong><a href="https://blog.cloudflare.com/emdash-wordpress/">Cloudflare is building a WordPress alternative for the edge</a></strong>: Cloudflare&#8217;s EmDash is positioned as a modern successor to WordPress, designed to run on Cloudflare&#8217;s edge or any Node.js server. It focuses on performance, simplicity, and a more developer-friendly architecture. The bigger signal is where platforms are heading. Content systems are moving closer to the edge, with infrastructure and CMS becoming tightly integrated.</p></li></ul><h1 style="text-align: center;"><strong>Beyond the Headlines</strong></h1><ul><li><p>&#129504; <strong><a href="https://read.engineerscodex.com/p/diving-into-claude-codes">What it&#8217;s like to actually use Claude Code</a></strong>: Claude Code is getting attention, but this deep dive looks past the hype into how it actually behaves in real workflows. From code navigation to multi-step reasoning, the experience feels less like autocomplete and more like collaborating with a system that understands intent. The gap between writing code and orchestrating it is starting to shrink.</p></li><li><p>&#128230; <strong><a href="https://wasp.sh/blog/2026/03/25/gentle-intro-npm-workspaces">npm workspaces finally make sense</a></strong>: As projects grow beyond a single folder, things start to break. Shared code drifts, dependencies duplicate, and workflows get messy. This guide breaks down how npm workspaces actually solve that by managing multiple packages in one repo with shared dependencies and seamless imports. The value is not just convenience. It is about building systems that scale without turning your codebase into a maintenance problem.</p></li><li><p>&#128293; <strong><a href="https://trigger.dev/blog/firebun">Trigger.dev got 5x performance by replacing Node with Bun</a></strong><a href="https://trigger.dev/blog/firebun">: </a>Trigger.dev swapped Node.js for Bun in a latency-critical service and saw throughput jump from ~2k to over 10k requests per second. The deeper insight is not just speed. It shows how runtime choices are starting to matter again, especially for systems handling high concurrency and long-lived connections.</p></li><li><p>&#128269; <strong><a href="https://www.buchodi.com/chatgpt-wont-let-you-type-until-cloudflare-reads-your-react-state-i-decrypted-the-program-that-does-it/">Why ChatGPT waits before you can type</a></strong>: A deep reverse-engineering effort by Buchodi digs into why ChatGPT sometimes blocks input until a background check completes. The analysis suggests Cloudflare&#8217;s Turnstile is not just verifying the browser, but checking whether the app itself has properly initialized, including parts of the React state. The bigger shift is subtle but important. Bot detection is moving beyond &#8220;is this a real browser&#8221; to &#8220;is this a real user interacting with a real app.&#8221;</p></li></ul><h1 style="text-align: center;"><strong>Tool of the Week</strong></h1><p>&#128250; <strong><a href="https://github.com/zhw2590582/ArtPlayer">Build your own YouTube-style player with ArtPlayer</a></strong> (<strong><a href="https://links.uk.defend.egress.com/Warning?crId=69cc1535d3081355e54d4b05&amp;Domain=packt.com&amp;Threat=eNpzrShJLcpLzAEADmkDRA%3D%3D&amp;Lang=en&amp;Base64Url=eNrLKCkpKLbS189KLEssTi7KLCgpT03NzqnUS87P1c_JzMvWN7QwNjAz07cwT01NM7IwtbAAAOgBESI%3D&amp;@OriginalLink=javascriptweekly.com">demo</a></strong>)</p><p>ArtPlayer is a full-featured HTML5 video player that gives you fine-grained control over the playback experience. From custom controls and subtitles to plugins and styling, it is designed to be deeply customizable without adding unnecessary complexity.</p><p>If you need more than a basic video tag but don&#8217;t want to build everything from scratch, this strikes a practical middle ground.</p><p><em>That&#8217;s all for this week. Have any ideas you want to see in the next article? Hit Reply!</em></p><p>Cheers!</p><p>Editor-in-chief,</p><p>Kinnari Chohan</p><div><hr></div><p><strong>&#128075; <a href="https://landing.packtpub.com/sponsorship-landing-page/">Advertise with us</a></strong><br><strong> </strong>Interested in sponsoring this newsletter and reaching a highly engaged audience of tech professionals? Simply reply to this email, and our team will get in touch with the next steps.</p>]]></content:encoded></item><item><title><![CDATA[WebDevPro #132: Async Code That Looks Fine but Fails in Production ]]></title><description><![CDATA[Crafting the Web: Tips, Tools, and Trends for Developers]]></description><link>https://packtwebdevpro.substack.com/p/webdevpro-132-async-code-that-looks</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/webdevpro-132-async-code-that-looks</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Mon, 30 Mar 2026 14:03:26 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/de891d2f-e06c-4f97-88b9-fc6f9f8d5834_497x442.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 style="text-align: center;"><strong><a href="https://www.eventbrite.com/e/hands-on-microservices-with-spring-boot-workshop-tickets-1981982956376?aff=newsletter1">Most Spring Boot projects stop at REST APIs</a></strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Mk3o!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F244dd6d2-4ce4-4dc0-a196-a5e7ce439e3a_1920x960.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Mk3o!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F244dd6d2-4ce4-4dc0-a196-a5e7ce439e3a_1920x960.png 424w, https://substackcdn.com/image/fetch/$s_!Mk3o!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F244dd6d2-4ce4-4dc0-a196-a5e7ce439e3a_1920x960.png 848w, https://substackcdn.com/image/fetch/$s_!Mk3o!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F244dd6d2-4ce4-4dc0-a196-a5e7ce439e3a_1920x960.png 1272w, https://substackcdn.com/image/fetch/$s_!Mk3o!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F244dd6d2-4ce4-4dc0-a196-a5e7ce439e3a_1920x960.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Mk3o!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F244dd6d2-4ce4-4dc0-a196-a5e7ce439e3a_1920x960.png" width="1456" height="728" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/244dd6d2-4ce4-4dc0-a196-a5e7ce439e3a_1920x960.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:728,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!Mk3o!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F244dd6d2-4ce4-4dc0-a196-a5e7ce439e3a_1920x960.png 424w, https://substackcdn.com/image/fetch/$s_!Mk3o!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F244dd6d2-4ce4-4dc0-a196-a5e7ce439e3a_1920x960.png 848w, https://substackcdn.com/image/fetch/$s_!Mk3o!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F244dd6d2-4ce4-4dc0-a196-a5e7ce439e3a_1920x960.png 1272w, https://substackcdn.com/image/fetch/$s_!Mk3o!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F244dd6d2-4ce4-4dc0-a196-a5e7ce439e3a_1920x960.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>Most Spring Boot developers stop at REST APIs. That&#8217;s enough to build demos but not to build systems that survive production.</p><p>The real work sits beyond that. Service discovery, resilience, observability, config management are what separate working code from systems that hold up under pressure.</p><p>You don&#8217;t pick this up from tutorials. It comes from building systems, making trade-offs, and seeing them run.</p><p>Tomorrow, you get exactly that.</p><p><strong>Live. From scratch. With Simon Martinelli and Josh Long.</strong></p><p><strong>Only 6 spots left.</strong></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.eventbrite.com/e/hands-on-microservices-with-spring-boot-workshop-tickets-1981982956376?aff=newsletter1&quot;,&quot;text&quot;:&quot;&#127903; Use code SPRING40 for 40% OFF&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.eventbrite.com/e/hands-on-microservices-with-spring-boot-workshop-tickets-1981982956376?aff=newsletter1"><span>&#127903; Use code SPRING40 for 40% OFF</span></a></p><div><hr></div><p>Welcome to this week&#8217;s issue of WebDevPro!</p><p>Have you ever written async code that looked perfectly fine, only for it to behave unpredictably later? It&#8217;s one of those things that feels obvious while coding, but starts to fall apart once real conditions come into play.</p><p>Asynchronous programming is fundamental to Node.js. The event loop keeps everything moving, delegating work and picking it back up when results return. On paper, it feels straightforward. You write code in sequence, so it should run that way too.</p><p>But that&#8217;s where things get tricky.</p><p>Execution is shaped by timing, scheduling, and resource contention. These are not visible in the code itself. What looks sequential can run concurrently. What feels predictable can change under load. Many real-world issues don&#8217;t come from syntax errors, but from how async behavior interacts with shared resources and execution order.</p><p>This week&#8217;s deep dive breaks down where these assumptions fail and what it takes to make async systems behave reliably.</p><p>Before we get into it, here&#8217;s this week at a glance:</p><p><em><strong>&#128998; <a href="https://devblogs.microsoft.com/typescript/">TypeScript is preparing for a compiler rewrite</a></strong></em></p><p><em><strong>&#128230; <a href="https://github.com/pnpm/pnpm/releases/tag/v11.0.0-beta.0">pnpm is redesigning how dependencies are stored</a></strong></em></p><p><em><strong>&#129302; <a href="https://www.youtube.com/watch?v=PXq6awYzfT8">Next.js is pushing toward AI-first app development</a></strong></em></p><p><em><strong>&#9889; <a href="https://x.com/felixrieseberg/status/2034688574239776778">Claude dropped SSR for speed gains</a></strong></em></p><p><em><strong>&#129513; <a href="https://storybook.js.org/blog/storybook-mcp-for-react/">Storybook is becoming AI-readable infrastructure</a></strong></em></p><h3><strong>When Async Execution Breaks Assumptions</strong></h3><p>A common source of failure is incorrect assumptions about execution order. Consider a case where two operations attempt to write to the same file. The code may appear sequential, but without explicit coordination, the operations execute independently.</p><p>In such scenarios, the following pattern is often observed:</p><p><code>async function raceCondition() { <br>const filename = ... <br>await unlink(filename) <br><br>writeFile(filename, &#8216;Written from first promise\n&#8217;, { flag: &#8216;a&#8217; }) <br>writeFile(filename, &#8216;Written from second promise\n&#8217;, { flag: &#8216;a&#8217; }) <br>}</code></p><p>At first glance, this code appears correct because two write operations are triggered one after the other. However, the absence of awaiting these operations means they run concurrently. Both operations attempt to access the same file at the same time.</p><p>This leads to inconsistent results, where the order of writes varies across executions. This behavior is known as a race condition. The issue is not syntax, but incorrect assumptions about how asynchronous execution works.</p><h3><strong>Concurrency Does Not Guarantee Order</strong></h3><p>In asynchronous systems, starting operations sequentially does not guarantee sequential execution. Each asynchronous call creates its own execution path, and these paths are resolved independently based on system timing.</p><p>When multiple operations target the same resource, they compete for access. Without explicit coordination, the runtime does not guarantee which operation completes first. The outcome becomes dependent on timing rather than intent.</p><p>This variability may not appear during development but becomes more prominent under production load, where multiple operations execute simultaneously.</p><h3><strong>Coordinating Access: Controlling Async Behavior</strong></h3><p>To prevent race conditions, access to shared resources must be controlled. One approach is to introduce a mechanism that ensures only one operation interacts with the resource at a time.</p><p>The following structure demonstrates this approach:</p><p><code>class FileWriter { <br>#isWriting = false <br>static instance = null <br><br>constructor() { <br>if (!FileWriter.instance) { <br>FileWriter.instance = this <br>} <br>return FileWriter.instance <br>} <br><br>async writeFile(filename, data) { <br>if (this.#isWriting) { <br>await setTimeout(250) <br>return this.writeFile(filename, data) <br>} <br><br>this.#isWriting = true <br>const result = await writeFile(filename, data, { flag: &#8216;a&#8217; }) <br>this.#isWriting = false <br>return result <br>} <br>}</code></p><p>This implementation introduces a lock mechanism. If a write operation is already in progress, subsequent operations wait before retrying. This ensures that writes occur sequentially rather than concurrently.</p><p>With coordination in place, execution becomes predictable. Without it, asynchronous code may behave inconsistently under real conditions.</p><h3><strong>Callback Hell: When Async Structure Breaks Readability</strong></h3><p>Asynchronous issues are not limited to execution order. They also affect how code is structured. Deeply nested callbacks create code that is difficult to read and maintain.</p><p>An example of this structure is shown below:</p><p><code>stepOne((err, resultOne) =&gt; { <br>stepTwo(resultOne, (err, resultTwo) =&gt; { <br>stepThree(resultTwo, (err, resultThree) =&gt; { <br>console.log(resultThree); <br>}); <br>}); <br>});</code></p><p>Although the code executes correctly, the nested structure makes it harder to follow the flow of data and control. Error handling is repeated at each level, increasing complexity.</p><p>As the number of steps increases, the difficulty of maintaining and debugging the code also increases.</p><h3><strong>The Event Loop and Hidden Blocking</strong></h3><p>Node.js relies on non-blocking operations to maintain performance. The event loop processes tasks and delegates work when possible, allowing other operations to continue executing.</p><p>However, not all operations are non-blocking. Some APIs perform blocking I/O, which pauses execution of the entire program until completion. This prevents the event loop from handling other tasks.</p><p>For example, cryptographic operations can block the main thread when executed synchronously. An asynchronous alternative allows work to be delegated externally:</p><p><code>generateKeyPair(&#8221;rsa&#8221;, { modulusLength: 1024 }, () =&gt; {})</code></p><p>The asynchronous version allows other operations to continue, while the synchronous version blocks execution. Under production load, blocking operations can significantly reduce system responsiveness.</p><h3><strong>Async Does Not Always Mean Non-Blocking</strong></h3><p>A common misconception is that wrapping a function in asynchronous code makes it non-blocking. This is not always true. If the underlying operation is blocking, it will still block execution.</p><p>In such cases, performance improvements come from reducing how often the operation runs rather than changing how it is invoked.</p><p>For example, caching results avoids repeated expensive computations:</p><p><code>let cachedSignature = null; <br><br>if (!cachedSignature) { <br>cachedSignature = signData(...) <br>}</code></p><p>This approach improves throughput by reducing execution frequency rather than altering execution style.</p><h3><strong>Async Behavior Under Load</strong></h3><p>Many asynchronous issues only become visible under load. In controlled development environments, operations often execute in predictable sequences, and resource contention is minimal. As a result, code that appears stable during testing can behave differently when multiple operations are triggered at the same time.</p><p>Race conditions become more apparent when concurrent requests attempt to access or modify the same resource. What may appear as an occasional inconsistency during development can become a frequent issue when the same code is executed repeatedly under higher traffic. The lack of coordination between asynchronous operations leads to unpredictable results, making these issues harder to reproduce and debug.</p><p>Blocking operations also have a more pronounced impact under load. When a synchronous task runs on the main thread, it prevents the event loop from processing other incoming requests. In low-traffic scenarios, this delay may not be noticeable. Under production conditions, where many requests arrive simultaneously, blocking behavior can cause cascading delays, reducing overall responsiveness.</p><p>Repeated execution of expensive operations further amplifies the problem. When the same computation is performed for every request without caching or reuse, system resources are consumed unnecessarily. This reduces throughput and increases response times, especially when multiple requests trigger the same operation concurrently.</p><p>Another important factor is timing variability. Asynchronous execution depends on system scheduling, resource availability, and workload distribution. Under load, these factors fluctuate more significantly, increasing the likelihood of inconsistent outcomes. Code that relies on implicit ordering or timing assumptions becomes less reliable as concurrency increases.</p><p>These issues highlight that asynchronous behavior is not only about writing non-blocking code, but also about understanding how that code behaves when multiple operations interact simultaneously. Without coordination, control over execution order, and careful management of shared resources, asynchronous systems can produce inconsistent results under real-world conditions.</p><h3><strong>Final words</strong></h3><p>Asynchronous programming enables Node.js to handle multiple operations efficiently, but it also introduces complexity in execution order, resource access, and performance.</p><p>Many failures are caused by incorrect assumptions about how asynchronous code behaves. These issues often remain hidden during development and only surface under production conditions.</p><p>Understanding how asynchronous code interacts with the event loop, shared resources, and system constraints is essential for building reliable applications.</p><h1 style="text-align: center;"><strong>This Week in the News</strong></h1><ul><li><p><strong>&#128998; <a href="https://devblogs.microsoft.com/typescript/">TypeScript 6.0 is really about TypeScript 7.0</a></strong>: TypeScript 6.0 quietly sets the stage for a bigger shift. This release moves the ecosystem closer to a Go-powered native compiler planned for TypeScript 7.0, with clear signals that performance and build speed are about to take a serious leap. It focuses less on surface-level features and more on groundwork that could reshape how large codebases compile and scale.</p></li><li><p>&#128230; <strong><a href="https://github.com/pnpm/pnpm/releases/tag/v11.0.0-beta.0">pnpm 11 Beta just changed how dependencies are stored</a></strong>: pnpm 11 Beta offers a glimpse into where package management is heading. The shift to a SQLite-powered store improves lookup speed and reliability, while a broader config overhaul simplifies how projects define and share settings. Stricter build security is now enabled by default, reflecting a growing focus on supply chain safety. This release feels less like an incremental update and more like a rethink of how dependencies are stored and secured.</p></li><li><p>&#129302; <strong><a href="https://www.youtube.com/watch?v=PXq6awYzfT8">Next.js just made AI apps feel native</a></strong>: Next.js 16.2 leans deeper into AI-native development. The update reshapes how developers connect model output to real interfaces, tightening the loop between prompting and product. The direction is becoming clear. Next.js is evolving into a foundation for AI-powered applications, not just a frontend framework.</p></li><li><p>&#9889; <strong><a href="https://x.com/felixrieseberg/status/2034688574239776778">Why Claude dropped SSR for a Vite-powered setup</a></strong>: Anthropic&#8217;s team shared how they made Claude and its desktop apps meaningfully faster by moving away from SSR to a static setup using Vite and TanStack Router. The shift highlights a growing pattern where speed and responsiveness win over traditional rendering models, especially for AI-heavy interfaces that demand instant feedback.</p></li><li><p>&#129513; <strong><a href="https://storybook.js.org/blog/storybook-mcp-for-react/">Storybook MCP brings AI into your UI workflow</a></strong>: Storybook&#8217;s latest update introduces an MCP server that lets coding agents understand your components at a deeper level. Instead of guessing structure, AI can now access metadata, generate stories, write tests, and even help fix bugs with more context. It signals a shift where component libraries are no longer just for developers, but also for the tools assisting them.</p></li></ul><h1 style="text-align: center;"><strong>Beyond the Headlines</strong></h1><ul><li><p>&#129504; <strong><a href="https://blog.sentry.io/setting-up-next-js-source-maps-sentry/">Fix your Next.js errors without exposing your code</a></strong>: Debugging production errors in Next.js often means staring at unreadable stack traces. This guide walks through setting up source maps with Sentry so errors point back to your actual code, not minified chunks. The key detail is balance. You get full visibility in Sentry while keeping source maps out of the browser, which protects your code and improves debugging at the same time.</p></li><li><p>&#128202;<strong> <a href="https://theconsensus.dev/p/2026/03/02/source-available-projects-and-their-ai-contribution-policies.html">Most open source projects are already accepting AI code</a></strong>: Phil Eaton surveyed 112 major source-available projects to understand how they handle AI-assisted contributions. The results show a clear trend. Most projects already allow or have accepted AI-generated code, with only a handful enforcing outright bans. The takeaway is not just policy, but reality. AI is already part of how modern open source evolves, and governance is still catching up</p></li><li><p><strong>&#9883;&#65039; <a href="https://dev.to/playfulprogramming/two-react-design-choices-developers-dont-like-but-cant-avoid-d6g">The React quirks you hate are actually fundamental</a></strong>: Some of React&#8217;s most disliked patterns, like deferred state updates and dependency arrays, are not accidental complexity. This piece argues they reflect deeper constraints of asynchronous UI systems. Once you look past the friction, they reveal problems every framework eventually has to solve, even the ones trying to replace React.</p></li><li><p>&#129513; <strong><a href="https://will-keleher.com/posts/small-programming-tricks-matter/">Small programming tricks shape how your code scales</a></strong>: Tiny habits compound. This piece explores how small implementation choices, often dismissed as style or preference, quietly influence readability, maintainability, and long-term velocity. It is a reminder that good engineering is rarely about big rewrites. It is built through consistent, low-level decisions that add up over time.</p></li></ul><h1 style="text-align: center;"><strong>Tool of the Week</strong></h1><p>&#9997;&#65039; <strong><a href="https://stroke.abhii.space/">Draw it once, animate it instantly</a></strong></p><p>Stroke turns rough sketches into production-ready animations. You draw directly in the browser, and it generates Motion-based code you can drop into a React or Next.js component. Under the hood, it converts your strokes into SVG paths and animates them without manual setup, making it ideal for signatures, logos, or playful UI details.</p><p><em>That&#8217;s all for this week. Have any ideas you want to see in the next article? Hit Reply!</em></p><p>Cheers!</p><p>Editor-in-chief,</p><p>Kinnari Chohan</p><div><hr></div><p><strong>&#128075; <a href="https://landing.packtpub.com/sponsorship-landing-page/">Advertise with us</a></strong><br><strong> </strong>Interested in sponsoring this newsletter and reaching a highly engaged audience of tech professionals? Simply reply to this email, and our team will get in touch with the next steps.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://packtwebdevpro.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Web Development Newsletter by Packt! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[WebDevPro #131: Building Reliable Applications with Cursor: A Spec-Driven Workflow for Incremental Development ]]></title><description><![CDATA[Crafting the Web: Tips, Tools, and Trends for Developers]]></description><link>https://packtwebdevpro.substack.com/p/webdevpro-131-building-reliable-applications</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/webdevpro-131-building-reliable-applications</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Mon, 23 Mar 2026 14:02:20 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!dKFE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35bf614f-47a0-4b5a-bb88-2cdea57f5802_800x400.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 style="text-align: center;"><strong><a href="https://www.eventbrite.com/e/hands-on-microservices-with-spring-boot-workshop-tickets-1981982956376?aff=newsletter1">Most Spring Boot projects stop at REST APIs</a></strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dKFE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35bf614f-47a0-4b5a-bb88-2cdea57f5802_800x400.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dKFE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35bf614f-47a0-4b5a-bb88-2cdea57f5802_800x400.png 424w, https://substackcdn.com/image/fetch/$s_!dKFE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35bf614f-47a0-4b5a-bb88-2cdea57f5802_800x400.png 848w, https://substackcdn.com/image/fetch/$s_!dKFE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35bf614f-47a0-4b5a-bb88-2cdea57f5802_800x400.png 1272w, https://substackcdn.com/image/fetch/$s_!dKFE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35bf614f-47a0-4b5a-bb88-2cdea57f5802_800x400.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dKFE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35bf614f-47a0-4b5a-bb88-2cdea57f5802_800x400.png" width="800" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/35bf614f-47a0-4b5a-bb88-2cdea57f5802_800x400.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!dKFE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35bf614f-47a0-4b5a-bb88-2cdea57f5802_800x400.png 424w, https://substackcdn.com/image/fetch/$s_!dKFE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35bf614f-47a0-4b5a-bb88-2cdea57f5802_800x400.png 848w, https://substackcdn.com/image/fetch/$s_!dKFE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35bf614f-47a0-4b5a-bb88-2cdea57f5802_800x400.png 1272w, https://substackcdn.com/image/fetch/$s_!dKFE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35bf614f-47a0-4b5a-bb88-2cdea57f5802_800x400.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>Real systems require service discovery, API gateways, centralized configuration, and built-in resilience. In this live, hands-on workshop, you&#8217;ll build a working microservices system end-to-end, define service boundaries, wire up discovery, configure a gateway, and handle failures properly.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.eventbrite.com/e/hands-on-microservices-with-spring-boot-workshop-tickets-1981982956376?aff=newsletter1&quot;,&quot;text&quot;:&quot;Get 40% off with code SAVE40&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.eventbrite.com/e/hands-on-microservices-with-spring-boot-workshop-tickets-1981982956376?aff=newsletter1"><span>Get 40% off with code SAVE40</span></a></p><div><hr></div><p>Welcome to this week&#8217;s issue of WebDevPro!</p><p>If you&#8217;ve been experimenting with tools like Cursor, you&#8217;ve probably had that moment where the output looks promising but not quite right. You tweak the prompt, try again, and end up chasing the result instead of building something stable.</p><p>What tends to work far better is not bigger prompts or more detailed instructions, but a shift toward a spec-driven, incremental workflow. One that mirrors how experienced developers already build systems, but adapts it to work effectively with AI-assisted coding environments.</p><p>In this article, we want to walk through a more reliable way to approach this. By the end, you&#8217;ll have a practical workflow for structuring your projects, breaking down features, and working with AI coding tools in a way that actually scales beyond small experiments.</p><h3><strong>Why direct prompting breaks down in real projects</strong></h3><p>It is tempting to treat Cursor as a high-powered code generator. Describe the app, mention the tech stack, and expect a complete implementation.</p><p>That approach holds up for small, disposable prototypes. It starts to fracture as soon as the project has multiple features, shared state, or evolving requirements.</p><p>There are a few reasons for this.</p><ul><li><p>First, ambiguity compounds quickly. Even a well-written prompt leaves room for interpretation. The model fills in those gaps based on patterns, not your intent.</p></li><li><p>Second, outputs are inherently variable. The same prompt can produce slightly different structures, naming conventions, or flows. This makes it difficult to build predictably.</p></li><li><p>Third, you give up control of the system&#8217;s shape. Instead of designing the architecture, you are reacting to whatever the model generates.</p></li></ul><p>The result is a loop of correction rather than a process of construction.</p><h3><strong>A more reliable approach: constrain, decompose, iterate</strong></h3><p>A more effective pattern is to treat the tool as a collaborator that works best within clearly defined boundaries.</p><p>The workflow is straightforward:</p><ul><li><p>Define what the system should do</p></li><li><p>Break it into discrete units of work</p></li><li><p>Implement those units incrementally</p></li><li><p>Refine through feedback</p></li></ul><p>This is familiar territory. The difference is that your artifacts, like specifications and task lists, are now also guiding the model.</p><h3><strong>Start with a specification that removes guesswork</strong></h3><p>Before opening Cursor, it helps to define how the application should behave in concrete terms. Consider a simple example: a math practice application for children.</p><p>At a glance, it sounds trivial. In practice, it involves a number of decisions:</p><ul><li><p>What kinds of operations are supported</p></li><li><p>How questions are presented</p></li><li><p>How users interact with answers</p></li><li><p>How incorrect attempts are tracked</p></li><li><p>What metrics are surfaced in a statistics view</p></li></ul><p>Writing this down in a structured format forces clarity. It also creates a shared reference point for every subsequent step.</p><p>One useful approach is to draft the specification in Markdown using a general-purpose language model. The key is not the initial output, but the interaction that follows. Asking the model to clarify uncertainties before generating the spec often leads to better results.</p><p>Once you have a draft, it is worth reviewing line by line. Fill in gaps, remove contradictions, and add constraints that matter to you. Visual expectations, state transitions, and edge cases are all worth capturing early.</p><p>The specification becomes less of a document and more of a contract. It defines intent in a way that both you and the tool can consistently refer back to.</p><h3><strong>Translate the specification into a phased TODO list</strong></h3><p>With a clear specification in place, the next step is to decompose it into manageable units of work.</p><p>Instead of thinking in terms of &#8220;build the app,&#8221; the focus shifts to &#8220;implement the next smallest meaningful piece.&#8221; A structured TODO list works well for this. Features are grouped into phases, and each phase contains tasks that can be completed independently.</p><p>For example:</p><h5><strong>Phase 1: Project setup</strong></h5><ul><li><p>Initialize React application</p></li><li><p>Configure styling system</p></li><li><p>Create base routing and placeholder pages</p></li></ul><h5><strong>Phase 2: Core interaction</strong></h5><ul><li><p>Generate math questions</p></li><li><p>Render question cards</p></li><li><p>Implement answer selection logic</p></li></ul><p>This breakdown serves two purposes: It reduces cognitive load. You are no longer juggling the entire system in your head. It also gives Cursor a much clearer target. Instead of interpreting a broad request, it can focus on a well-defined task.</p><h3><strong>Build incrementally and keep the scope tight</strong></h3><p>With the TODO list in place, you can begin implementing features in Cursor. The important shift here is how you frame your prompts. Rather than asking for a full implementation, you anchor the request to specific artifacts and a limited scope:</p><p><em><strong>Use the specification and TODO list to complete Phase 1. Mark completed tasks.</strong></em></p><p>This keeps the model grounded. It knows where to look for context and what success looks like. In the case of the math practice app, the first phase might result in:</p><ul><li><p>A scaffolded React project</p></li><li><p>Basic routing</p></li><li><p>Placeholder pages such as Home, Practice, Stats, and Settings</p></li></ul><p>At this stage, the application is simple, but functional. That is intentional. Each phase establishes a stable base for the next.</p><h3><strong>Iterate deliberately instead of restarting</strong></h3><p>Once the initial output is in place, the next step is refinement.</p><p>It is common for the first version of the UI or structure to feel underdeveloped. The instinct might be to rewrite the prompt or regenerate the feature from scratch. A more effective approach is to iterate on top of what already exists.</p><p>For example:</p><p><em><strong>Improve the homepage layout. Add clearer navigation and better spacing.</strong></em></p><p>This kind of prompt is focused and contextual. It builds on existing work rather than replacing it.</p><p>Over time, this creates a steady progression:</p><ul><li><p>Initial structure</p></li><li><p>Incremental improvements</p></li><li><p>Targeted fixes</p></li></ul><p>Each step is small, but collectively they move the system toward a more polished state.</p><h3><strong>Designing for variability instead of fighting it</strong></h3><p>One characteristic of working with language models is that outputs are not perfectly consistent. Even with the same inputs, you may see variations in structure, naming, or implementation details. Rather than trying to eliminate this variability, it helps to account for it in your workflow.</p><p>Specifications anchor intent.<br>TODO lists constrain scope.<br>Incremental development limits the blast radius of changes.</p><p>Together, these reduce the impact of variation. You retain control over the system, even as the underlying outputs shift slightly.</p><h3><strong>A closer look at a single feature</strong></h3><p>To make this more concrete, consider the first phase of the math practice application. The goal is to establish the basic application shell. You begin with two inputs:</p><ul><li><p>A specification that defines pages and navigation</p></li><li><p>A TODO list that outlines setup tasks</p></li></ul><p>The prompt is simple and scoped:</p><p><em><strong>Complete Phase 1 using the provided specification and TODO list.</strong></em></p><p>Cursor initializes the project, sets up dependencies, and creates the necessary files. You run the application locally and see a basic interface with navigation between pages. At this point, the system is functional but minimal. You then refine:</p><p><em><strong>Improve the visual structure of the homepage and navigation.</strong></em></p><p>The tool updates components, adjusts layout, and introduces better spacing. You review the changes, keep what works, and continue. This pattern repeats for each feature. The system grows in layers, each one built on a stable foundation.</p><h3><strong>Patterns that hold up in larger projects</strong></h3><p>A few patterns consistently make this approach effective. Clear specifications reduce the need for corrective prompts later. They shift effort from fixing outputs to shaping intent early.</p><p>Breaking work into smaller tasks improves <strong>reliability</strong>. Each unit is easier for the model to interpret and implement correctly.</p><p><strong>Iteration</strong> keeps progress steady. Instead of waiting for a perfect result, you move forward through a series of improvements.</p><p><strong>Documentation</strong> becomes an active part of the process. Specifications and TODO lists evolve alongside the code, keeping everything aligned.</p><p>Most importantly, you remain in control of the system&#8217;s design. The tool accelerates execution, but the direction still comes from you. But<strong> </strong>this workflow is not automatic. It depends on a few habits.</p><p><em>If the specification is vague, the outputs will reflect that.<br>If tasks are too large, the results become inconsistent again.<br>If changes are accepted without review, small issues compound over time.</em></p><p>The tool amplifies the process you bring to it. Structure leads to leverage. Lack of structure leads to friction.</p><h3><strong>Closing thoughts</strong></h3><p>Working with Cursor is less about mastering prompts and more about shaping a reliable development process. Once you move away from one-shot generation and toward a spec-driven, incremental approach, the experience changes. The tool becomes more predictable. The codebase becomes easier to reason about. Progress feels steadier.</p><p>In many ways, this is not a new way of building software. It is a return to fundamentals, adapted for a new interface. The difference is that when the structure is right, the speed at which you can move begins to compound.</p><p>If you want to go deeper into this way of working, especially with hands-on examples and a full project walkthrough, this approach is explored in detail in <em><strong><a href="https://www.amazon.com/Vibe-Coding-Cursor-Windsurf-Lovable/dp/180730163X">Vibe Coding with Cursor</a></strong></em>. It&#8217;s a practical guide to building real applications using these patterns, and a useful next step if you&#8217;re looking to move beyond experimentation into something more structured.</p><h1 style="text-align: center;"><strong>This Week in the News</strong></h1><ul><li><p><strong>&#129302; <a href="https://openai.com/index/openai-to-acquire-astral/">OpenAI to acquire Astral</a>: </strong>OpenAI is acquiring Astral and its widely used open-source Python developer tools, including uv, Ruff, and ty. The move strengthens OpenAI&#8217;s push into developer tooling, bringing core workflows like dependency management, linting, and type checking closer to its ecosystem. The goal is to accelerate Codex beyond code generation, positioning it to operate across the full development lifecycle, where it can work directly within the tools developers already use.</p></li><li><p><strong>&#128467;&#65039; <a href="https://futuresearch.ai/blog/javascript-thinks-everythings-a-date/">Why JavaScript still struggles with dates</a></strong>: The JavaScript new Date(someString) constructor is notoriously over-eager, stemming from legacy C++ parsers in engines like V8 and SpiderMonkey that aggressively &#8220;guess&#8221; date components to maintain backwards compatibility. This leads to absurd &#8220;hallucinations&#8221; where the engine prioritizes finding a year at any cost. Beyond these quirks, the parser&#8217;s inconsistency is a frequent source of production bugs; for instance, new Date(&#8221;2024-03-25&#8221;) is treated as UTC, while adding a time element like T00:00 shifts it to Local Time, often causing &#8220;off-by-one-day&#8221; errors for users in different time zones. To avoid silent data corruption, such as new Date(null) defaulting to the 1970 Unix Epoch, developers should abandon these loose string constructors in favor of strict ISO 8601 formatting or the modern, predictable <strong>Temporal API</strong>.</p></li><li><p>&#9650; <strong><a href="https://nextjs.org/blog/next-16-2">Next.js 16.2 updates</a></strong>: Next.js 16.2 introduces a set of refinements focused on improving performance, stability, and the overall developer experience. The release builds on recent changes to the app router and server components, with updates that make common workflows more predictable and easier to manage. The direction remains consistent, with Vercel continuing to smooth out rough edges while aligning Next.js more closely with modern React patterns and production needs.</p></li><li><p><strong>&#9889;<a href="https://vite.dev/blog/announcing-vite8">Vite 8 and </a><a href="https://void.cloud/">Void</a><a href="https://vite.dev/blog/announcing-vite8">, the fill-stack pivot</a></strong>: The Vite ecosystem is expanding beyond build tooling. Alongside the release of Vite 8, which brings updates focused on faster builds and a more streamlined developer experience, the VoidZero team has introduced Void, a Vite-native deployment platform built on Cloudflare Workers. Void aims to turn Vite apps into full-stack applications by bundling capabilities like databases, KV storage, object storage, and AI inference directly into the workflow. Together, these updates signal a shift toward a more integrated Vite stack that spans both development and deployment.</p></li><li><p><strong>&#9878;&#65039; <a href="https://github.com/indutny/no-ai-in-nodejs-core">No AI code in Node.js core? A new petition sparks debate</a>: </strong>A long-running discussion around AI-assisted development in OpenJS Foundation projects has taken a new turn. A Node.js contributor has started a petition urging the TSC to restrict AI-generated code from being merged into Node&#8217;s core, following concerns raised alongside a large 19K LOC PR. The <strong><a href="https://github.com/openjs-foundation/cross-project-council/issues/1509">debate</a> </strong>touches on deeper questions around code quality, maintainability, and ownership as AI becomes a common part of development workflows.</p></li><li><p><strong>&#129513; <a href="https://www.youtube.com/watch?v=9yI5cgFAhTw">How TanStack approaches modern developer tooling</a></strong>: TanStack shares a set of ecosystem updates alongside a detailed talk that breaks down the thinking behind its tooling approach. The focus stays on building framework-agnostic, composable primitives that can scale across different application architectures without locking developers into a specific stack. The talk offers a deeper look into how these decisions play out in practice, from managing server state to structuring UI logic, and why flexibility and interoperability remain central to TanStack&#8217;s design philosophy.</p></li></ul><h1 style="text-align: center;"><strong>Beyond the Headlines</strong></h1><ul><li><p><strong>&#128201; <a href="https://addyosmani.com/blog/comprehension-debt/">The hidden cost of &#8220;comprehension debt&#8221;</a></strong>: Addy Osmani introduces the idea of <em>comprehension debt</em>: the growing gap between how quickly code can be produced and how easily it can be understood. As tools (especially AI) accelerate code generation, the burden shifts to developers who need to read, debug, and maintain that code. It&#8217;s a useful lens for thinking about long-term code quality. Fast output is valuable, but only if teams can still reason about what they&#8217;ve built.</p></li><li><p><strong>&#129504; <a href="https://strawberrybrowser.com/blog/react-to-svelte">React to Svelte migration with AI agents</a></strong>: Strawberry shares how it rewrote 130K lines of React code to Svelte in just two weeks using coding agents, cutting UI complexity and doubling performance in the process. The write-up goes deeper into why the team moved away from React&#8217;s rendering model toward Svelte&#8217;s compiler-first approach, and how AI-assisted workflows made a full rewrite practical at a scale that would usually take months. It&#8217;s a strong signal of how framework decisions, performance constraints, and AI-driven development are starting to converge in real-world systems.</p></li><li><p><strong>&#127909; <a href="https://www.youtube.com/watch?v=oGktdQ45bTg">Rethinking how we build modern web apps</a>: </strong>This talk explores how modern web development is evolving, touching on architecture, tooling, and the trade-offs developers face as applications grow in complexity. It&#8217;s a useful watch if you&#8217;re thinking about how today&#8217;s patterns scale in real-world systems.</p></li><li><p><strong>&#128644; <a href="https://fidget-spinner.github.io/posts/jit-on-track.html">Understanding how JIT affects runtime performance</a></strong>: This post explores how Just-In-Time (JIT) compilation behaves in practice, looking at how execution performance evolves over time. It offers a deeper look at runtime optimizations and how they impact real-world performance characteristics.</p></li></ul><h1 style="text-align: center;"><strong>Tool of the Week</strong></h1><p><strong>&#128269; <a href="https://difftastic.wilfred.me.uk/">Understand code changes with structural diffs</a></strong></p><p>Traditional diffs compare text line by line, which can make complex changes hard to follow. <strong>Difftastic</strong> takes a different approach by comparing the syntax tree of your code, helping you see what actually changed at a structural level.</p><p>It supports multiple languages and highlights meaningful differences, making it especially useful when reviewing refactors or large code updates.</p><p><em>That&#8217;s all for this week. Have any ideas you want to see in the next article? Hit Reply!</em></p><p>Cheers!</p><p>Editor-in-chief,</p><p>Kinnari Chohan</p><div><hr></div><p><strong>&#128075; <a href="https://landing.packtpub.com/sponsorship-landing-page/">Advertise with us</a></strong><br><strong> </strong>Interested in sponsoring this newsletter and reaching a highly engaged audience of tech professionals? Simply reply to this email, and our team will get in touch with the next steps.</p>]]></content:encoded></item><item><title><![CDATA[WebDevPro #130: Rethinking State Management in Modern React]]></title><description><![CDATA[Crafting the Web: Tips, Tools, and Trends for Developers]]></description><link>https://packtwebdevpro.substack.com/p/webdevpro-130-rethinking-state-management</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/webdevpro-130-rethinking-state-management</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Mon, 16 Mar 2026 14:02:18 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Osr_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7a90243-d19c-4508-8fb1-8a2cb255523a_800x400.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 style="text-align: center;"><strong><a href="https://www.eventbrite.com/e/hands-on-microservices-with-spring-boot-workshop-tickets-1981982956376?aff=newsletter1">Most Spring Boot projects stop at REST APIs</a></strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Osr_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7a90243-d19c-4508-8fb1-8a2cb255523a_800x400.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Osr_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7a90243-d19c-4508-8fb1-8a2cb255523a_800x400.png 424w, https://substackcdn.com/image/fetch/$s_!Osr_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7a90243-d19c-4508-8fb1-8a2cb255523a_800x400.png 848w, https://substackcdn.com/image/fetch/$s_!Osr_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7a90243-d19c-4508-8fb1-8a2cb255523a_800x400.png 1272w, https://substackcdn.com/image/fetch/$s_!Osr_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7a90243-d19c-4508-8fb1-8a2cb255523a_800x400.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Osr_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7a90243-d19c-4508-8fb1-8a2cb255523a_800x400.png" width="800" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a7a90243-d19c-4508-8fb1-8a2cb255523a_800x400.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!Osr_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7a90243-d19c-4508-8fb1-8a2cb255523a_800x400.png 424w, https://substackcdn.com/image/fetch/$s_!Osr_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7a90243-d19c-4508-8fb1-8a2cb255523a_800x400.png 848w, https://substackcdn.com/image/fetch/$s_!Osr_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7a90243-d19c-4508-8fb1-8a2cb255523a_800x400.png 1272w, https://substackcdn.com/image/fetch/$s_!Osr_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7a90243-d19c-4508-8fb1-8a2cb255523a_800x400.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>Real systems require service discovery, API gateways, centralized configuration, and built-in resilience. In this live, hands-on workshop, you&#8217;ll build a working microservices system end-to-end, define service boundaries, wire up discovery, configure a gateway, and handle failures properly.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.eventbrite.com/e/hands-on-microservices-with-spring-boot-workshop-tickets-1981982956376?aff=newsletter1&quot;,&quot;text&quot;:&quot;Register and get 40% off - code SAVE40&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.eventbrite.com/e/hands-on-microservices-with-spring-boot-workshop-tickets-1981982956376?aff=newsletter1"><span>Register and get 40% off - code SAVE40</span></a></p><div><hr></div><p>Welcome to this week&#8217;s issue of WebDevPro!</p><p>If you&#8217;ve worked with React for a while, you&#8217;ve probably run into the same recurring question: <em><strong>how should we manage state in this application?</strong></em></p><p>State management is one of those topics that almost every React team ends up debating sooner or later. Should everything live in context? Do we need a global store? Would something like Zustand make things simpler?</p><p>Those conversations usually focus on tools. But in many cases the real problem shows up earlier than that.</p><p>In practice, React applications rarely become difficult to maintain because the wrong library was chosen. They become difficult to maintain because different kinds of state get handled in the same way.</p><p>A form input, an API response, a UI filter, and a shared user object often end up managed with identical patterns. That is where complexity starts to creep in.</p><p>In this article, we will look at the main categories of state that appear in React applications and how each category is best managed. By the end, you will have a clearer way to decide where state belongs in a React app, whether that means local component state, shared state, server data tools, or even the URL itself.</p><h3><strong>Not all state belongs in the same place</strong></h3><p>State in React applications usually falls into a few clear categories.</p><p><strong>Local state</strong> lives inside a single component. A dropdown menu, a modal visibility toggle, or a small UI interaction typically belongs here. Hooks such as useState or useReducer work well because the logic remains isolated.</p><p><strong>Server state</strong> represents data fetched from APIs or databases. This includes user profiles, product listings, or analytics data. The key difference is that the source of truth lives outside the application.</p><p><strong>Form state</strong> includes field values, validation errors, and submission status. Forms have their own lifecycle and benefit from specialized tools such as React Hook Form or React&#8217;s form hooks.</p><p><strong>URL state</strong> stores small pieces of UI state in route or search parameters. Tabs, filters, pagination, and search queries often belong here.</p><p><strong>Shared state</strong> exists when multiple components need access to the same data. Authentication details, application settings, or user preferences are common examples.</p><p>Understanding these categories clarifies an important point. React state is not a single problem. It is a set of related problems that require different solutions.</p><h3><strong>The easiest state to manage is the state you never store</strong></h3><p>One of the most common sources of complexity in React applications comes from duplicated state.</p><p>Consider a list of items where the interface displays only active entries. A common pattern stores both the original list and a filtered version of it.</p><p><code>const [items, setItems] = useState([...])</code></p><p><code>const [filteredItems, setFilteredItems] = useState([])</code></p><p><code>useEffect(() =&gt; {</code></p><p><code>setFilteredItems(items.filter(item =&gt; item.active))</code></p><p><code>}, [items])</code></p><p>This introduces synchronization logic that React must maintain.</p><p>A simpler approach derives the filtered list directly from the original state.</p><p><code>const [items, setItems] = useState([...])</code></p><p><code>const filteredItems = items.filter(item =&gt; item.active)</code></p><p>The application now maintains a single source of truth. React calculates the derived value when needed.</p><p>Derived state reduces bugs and simplifies reasoning about data flow. Many React components become easier to maintain once unnecessary state variables disappear.</p><h3><strong>Shared state is where React applications become complicated</strong></h3><p>Local state remains predictable because it stays within a component. Shared state changes that dynamic because multiple components read and update the same values.</p><p>Developers often encounter this situation when user data, permissions, or global settings must appear across different sections of the interface.</p><p>The simplest approach begins with <strong>prop drilling</strong>. A parent component holds the state and passes it through props to child components.</p><p>This technique often receives criticism, yet it works well for a small number of adjacent components. It also keeps data flow explicit and easy to trace.</p><p>Problems appear when the component tree becomes deeper. Intermediate components may receive props they do not use, simply to pass them further down the hierarchy.</p><p>At this stage, many teams introduce <strong>React context</strong>.</p><p>Context allows components to access shared values without passing them through each level of the tree. A provider component stores the shared state and exposes it to any descendant component.</p><p>This pattern simplifies access but introduces a different trade-off. When context values change, every consumer beneath the provider may re-render. For small applications this rarely matters. In larger interfaces the rendering behavior becomes harder to control.</p><p>Libraries such as <strong>Zustand</strong> approach shared state from a different angle. Zustand creates a centralized store and allows components to subscribe only to the pieces of state they require.</p><p><code>const userName = useUserStore(state =&gt; state.userName)</code></p><p>Components update only when the subscribed value changes. This selective subscription reduces unnecessary renders and keeps the shared state logic compact.</p><p>Context and Zustand both solve shared state challenges, but they operate at different scales. Context works well for moderate application state. Zustand becomes attractive once shared state spreads across larger parts of the interface.</p><h3><strong>Server state follows a different lifecycle</strong></h3><p>Data fetched from external services introduces a different category of state entirely.</p><p>Server data involves caching, background refetching, loading indicators, and stale data management. Handling these concerns with useState and useEffect often leads to repetitive code and fragile synchronization.</p><p>Libraries such as <strong>TanStack Query</strong> address this layer directly. They treat server data as cached resources rather than ordinary component state.</p><p>Components request data using a shared query key.</p><p><code>const { data } = useQuery({</code></p><p><code>queryKey: [&#8217;user&#8217;, userId],</code></p><p><code>queryFn: fetchUser</code></p><p><code>})</code></p><p>TanStack Query stores the response in a client cache. Other components requesting the same query receive the cached result rather than triggering another network request.</p><p>This model separates server data concerns from UI logic. React components remain focused on rendering rather than managing asynchronous data lifecycles.</p><h3><strong>Some state belongs in the URL</strong></h3><p>Another overlooked location for state is the browser address bar.</p><p>Interfaces often contain UI state that describes how a page is being viewed. Active tabs, filter selections, search queries, and pagination indexes all fall into this category.</p><p>Storing this information in URL search parameters creates several benefits.</p><p>The state becomes shareable through links. Refreshing the page preserves the interface configuration. Browser navigation also restores previous UI states naturally.</p><p>Framework hooks such as useSearchParams and routing utilities make this pattern straightforward.</p><p><code>const params = useSearchParams()</code></p><p><code>const activeTab = params.get(&#8217;tab&#8217;)</code></p><p>Many teams duplicate this information inside React state and attempt to synchronize it with the URL. Removing that duplication simplifies the architecture.</p><p>The address bar can act as a reliable source of truth for small pieces of UI state.</p><h3><strong>Choosing the right home for state</strong></h3><p>Modern React offers many tools for managing state, but the real skill lies in recognizing where each type of state belongs.</p><p>Local UI interactions usually remain simplest when handled with component state.</p><p>Values that can be computed from existing data should be derived instead of stored.</p><p>Data fetched from APIs benefits from tools designed for server state, such as TanStack Query, which handle caching and refetching automatically.</p><p>UI state that affects navigation, such as active tabs or filters, often works best when stored in URL parameters.</p><p>Shared client state can start with straightforward prop passing and evolve into solutions such as context or Zustand when multiple components need coordinated access.</p><p>The key takeaway is not which library to choose. It is learning to recognize the nature of the state problem in front of you. Once you can distinguish between local, shared, server, form, and URL state, the architecture decisions become much clearer. Instead of forcing every problem into the same pattern, each piece of state can live in the place where it is easiest to manage.</p><p>That shift in thinking leads to React applications that are easier to reason about, easier to scale, and far less prone to the state management issues that often slow teams down.</p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4T6s!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e484e30-226d-4800-8e6b-a531835565af_1200x675.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4T6s!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e484e30-226d-4800-8e6b-a531835565af_1200x675.png 424w, https://substackcdn.com/image/fetch/$s_!4T6s!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e484e30-226d-4800-8e6b-a531835565af_1200x675.png 848w, https://substackcdn.com/image/fetch/$s_!4T6s!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e484e30-226d-4800-8e6b-a531835565af_1200x675.png 1272w, https://substackcdn.com/image/fetch/$s_!4T6s!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e484e30-226d-4800-8e6b-a531835565af_1200x675.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4T6s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e484e30-226d-4800-8e6b-a531835565af_1200x675.png" width="1200" height="675" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1e484e30-226d-4800-8e6b-a531835565af_1200x675.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:675,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!4T6s!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e484e30-226d-4800-8e6b-a531835565af_1200x675.png 424w, https://substackcdn.com/image/fetch/$s_!4T6s!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e484e30-226d-4800-8e6b-a531835565af_1200x675.png 848w, https://substackcdn.com/image/fetch/$s_!4T6s!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e484e30-226d-4800-8e6b-a531835565af_1200x675.png 1272w, https://substackcdn.com/image/fetch/$s_!4T6s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e484e30-226d-4800-8e6b-a531835565af_1200x675.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://www.humblebundle.com/books/llm-and-agentic-ai-career-accelerator-bundle-packt-books?">Build real skills in LLMs and agentic AI with this 20+ course Packt bundle, featuring titles like </a><em><a href="https://www.humblebundle.com/books/llm-and-agentic-ai-career-accelerator-bundle-packt-books?">Learn Python Programming, 4E</a></em><a href="https://www.humblebundle.com/books/llm-and-agentic-ai-career-accelerator-bundle-packt-books?"> and </a><em><a href="https://www.humblebundle.com/books/llm-and-agentic-ai-career-accelerator-bundle-packt-books?">The LLM Engineer&#8217;s Handbook</a></em><a href="https://www.humblebundle.com/books/llm-and-agentic-ai-career-accelerator-bundle-packt-books?">. Learn how to design and deploy intelligent systems while supporting World Central Kitchen.</a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.humblebundle.com/books/llm-and-agentic-ai-career-accelerator-bundle-packt-books?&quot;,&quot;text&quot;:&quot;Grab the bundle!&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.humblebundle.com/books/llm-and-agentic-ai-career-accelerator-bundle-packt-books?"><span>Grab the bundle!</span></a></p><div><hr></div><h1 style="text-align: center;"><strong>This Week in the News</strong></h1><ul><li><p><strong>&#129504; <a href="https://devblogs.microsoft.com/typescript/announcing-typescript-6-0-rc/">TypeScript 6.0 RC prepares the ecosystem for the Go-powered compiler</a></strong>: TypeScript 6.0 RC has landed and it marks an important transition for the language. This release functions largely as a stepping stone toward TypeScript 7.0, which will introduce a new native compiler written in Go. The RC itself contains only a few small changes compared to the beta, but the bigger shift lies in the groundwork being laid for the next generation of the toolchain. Required updates to tsconfig.json help projects align with upcoming architecture changes, giving teams time to prepare before the performance gains of the Go-powered compiler arrive later this year.</p></li><li><p>&#9883;&#65039; <strong><a href="https://github.com/solidjs/solid/releases/tag/v2.0.0-beta.0">SolidJS 2.0 beta introduces first-class async and a redesigned reactive core</a></strong>: SolidJS has entered the 2.0 beta phase after several years of experimental work on its next-generation reactive system. The release introduces major architectural changes including a rewritten signals implementation, deterministic batching, and first-class async support built directly into the framework&#8217;s primitives. New patterns such as <code>action</code> and optimistic state helpers aim to make server mutations and UI updates easier to manage, while updates to control flow and rendering bring several breaking changes developers will notice quickly. The beta sets the stage for broader ecosystem updates ahead of the stable 2.0 release.</p></li><li><p><strong>&#9729;&#65039; <a href="https://astro.build/blog/astro-6/?ck_subscriber_id=3136909587">Astro 6 introduces a Rust compiler and deeper Cloudflare alignment</a></strong>: Astro 6 arrives as the framework&#8217;s first major release since its acquisition by Cloudflare in January, and the platform direction is already becoming clearer. The update introduces an experimental Rust compiler that will eventually replace the original Go-based .astro compiler, promising faster builds and a modernized compilation pipeline. Development workflows also improve through Vite&#8217;s new Environment API, which allows developers to run the exact production runtime during development. Astro also introduces a new Fonts API that simplifies custom font handling across projects.</p></li><li><p><strong>&#127754; <a href="https://blog.cloudflare.com/a-better-web-streams-api/">Cloudflare pushes for a simpler modern JavaScript Streams API</a></strong>: Cloudflare engineers are questioning the design of the Web Streams API, arguing that it reflects an earlier era of JavaScript before patterns like async iteration became common. The result is an abstraction that often feels overly complex, with specialized readers, locking mechanics, and extra boilerplate. Cloudflare proposes a simpler model built on modern JavaScript primitives that could improve both ergonomics and performance. Early benchmarks suggest potential speedups of up to 120&#215; across runtimes such as Node.js, Deno, and Workers. In a related talk, James Snell explains how an async-iterator-driven approach could make streaming code easier to reason about for developers working with edge platforms and large data pipelines. &#127909; Watch the talk: </p><div id="youtube2-abbeIUOCzmw" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;abbeIUOCzmw&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/abbeIUOCzmw?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div></li></ul><h1 style="text-align: center;"><strong>Beyond the Headlines</strong></h1><ul><li><p><strong>&#129302; <a href="https://silly.business/blog/we-should-revisit-literate-programming-in-the-agent-era">Literate programming may finally make sense in the AI agent era</a>: </strong>Donald Knuth&#8217;s idea of literate programming asked developers to write code as a narrative meant for humans, with the compiler following along. For decades the concept remained mostly academic. This piece revisits the idea through the lens of AI-assisted development, where agents read, analyze, and generate code alongside developers. Clear explanations, structured reasoning, and intent-rich programs suddenly become far more valuable. The argument is simple but compelling: the rise of coding agents may finally make literate programming practical.</p></li><li><p><strong>&#128024; <a href="https://nesbitt.io/2026/03/10/just-use-postgres.html">Just use Postgres and delay the infrastructure sprawl</a>: </strong>Many modern stacks quickly grow into a collection of specialized tools: queues, search services, analytics systems, and caches. This article argues that much of that complexity arrives too early. PostgreSQL already includes powerful capabilities such as JSON support, full-text search, background jobs, and extensions that cover a surprising range of workloads. For many products, a single Postgres database can carry far more responsibility than teams assume. The takeaway is pragmatic: lean on Postgres longer and introduce new infrastructure only when the workload genuinely demands it.</p></li><li><p><strong>&#9889;<a href="https://alexop.dev/posts/building-real-time-todo-app-jazz-vue/">Building a real-time collaborative to-do app with Jazz and Vue</a></strong>: Real-time collaboration often brings complex backend logic, synchronization challenges, and WebSocket plumbing. This tutorial shows a simpler path by building a collaborative to-do app using Jazz and Vue. The stack manages shared state and synchronization automatically, allowing the interface to update instantly as multiple users interact with the same data. The walkthrough focuses on how collaborative state flows through the application and how the UI reflects updates in real time. It offers a practical introduction to modern tooling for building collaborative applications.</p></li><li><p><strong>&#9883;&#65039; <a href="https://inside-react.vercel.app/blog/understanding-why-react-fiber-exists">Why React needed Fiber and what problem it actually solved</a></strong>: React Fiber is one of the biggest architectural changes in React&#8217;s history, yet its purpose is often misunderstood. This deep dive explains why the original reconciliation algorithm struggled with large or complex updates. Fiber introduced a scheduling model that allows React to pause, resume, and prioritize rendering work instead of processing everything in one blocking pass. That change laid the foundation for features such as concurrent rendering and smoother user experiences under heavy workloads.</p></li></ul><h1 style="text-align: center;"><strong>Tool of the Week</strong></h1><p><strong>&#128736;&#65039; <a href="https://github.com/cosmiciron/vmprint?utm_source=chatgpt.com">VMPrint deterministic PDF generation without headless browsers</a></strong></p><p>Print-to-PDF pipelines often rely on headless Chrome, bringing along browser quirks and inconsistent rendering. VMPrint takes a different approach with a pure TypeScript typesetting engine that bypasses the DOM entirely and computes layout through typographic math. The result is deterministic output across browsers, Node.js, and edge runtimes like Cloudflare Workers. Given identical input, VMPrint guarantees identical layout down to the sub-point position of every glyph. For teams building document generation pipelines or publishing systems, it offers a precise and reproducible alternative to browser-based rendering.</p><p><em>That&#8217;s all for this week. Have any ideas you want to see in the next article? Hit Reply!</em></p><div><hr></div><p>Cheers!</p><p>Editor-in-chief,</p><p>Kinnari Chohan</p>]]></content:encoded></item><item><title><![CDATA[WebDevPro #129: Why Single Page Applications Changed How We Build Web Apps]]></title><description><![CDATA[Crafting the Web: Tips, Tools, and Trends for Developers]]></description><link>https://packtwebdevpro.substack.com/p/webdevpro-129-why-single-page-applications</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/webdevpro-129-why-single-page-applications</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Mon, 09 Mar 2026 14:03:10 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!CCCe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1><strong><a href="https://www.eventbrite.com/e/hands-on-microservices-with-spring-boot-workshop-tickets-1981982956376?aff=newsletter1">Most Spring Boot projects stop at REST APIs</a></strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://www.eventbrite.com/e/hands-on-microservices-with-spring-boot-workshop-tickets-1981982956376?aff=newsletter1" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CCCe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png 424w, https://substackcdn.com/image/fetch/$s_!CCCe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png 848w, https://substackcdn.com/image/fetch/$s_!CCCe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png 1272w, https://substackcdn.com/image/fetch/$s_!CCCe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CCCe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png" width="800" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&quot;type&quot;:null,&quot;href&quot;:&quot;https://www.eventbrite.com/e/hands-on-microservices-with-spring-boot-workshop-tickets-1981982956376?aff=newsletter1&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!CCCe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png 424w, https://substackcdn.com/image/fetch/$s_!CCCe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png 848w, https://substackcdn.com/image/fetch/$s_!CCCe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png 1272w, https://substackcdn.com/image/fetch/$s_!CCCe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.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>Real systems require service discovery, API gateways, centralized configuration, and built-in resilience. In this live, hands-on workshop, you&#8217;ll build a working microservices system end-to-end, define service boundaries, wire up discovery, configure a gateway, and handle failures properly.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.eventbrite.com/e/hands-on-microservices-with-spring-boot-workshop-tickets-1981982956376?aff=newsletter1&quot;,&quot;text&quot;:&quot;Get 40% off with code SAVE40&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.eventbrite.com/e/hands-on-microservices-with-spring-boot-workshop-tickets-1981982956376?aff=newsletter1"><span>Get 40% off with code SAVE40</span></a></p><div><hr></div><p>Welcome to this week&#8217;s issue of WebDevPro!</p><p>Take a moment to think about the web apps you use every day. A dashboard updates without refreshing the page. A chat window receives messages in real time. A project board moves tasks across columns instantly.</p><p>Modern web applications behave very differently from traditional websites. Interfaces update instantly, dashboards refresh without reloading the page, and navigation feels closer to using installed software than browsing documents. This experience is powered by an architectural shift called the Single Page Application, or SPA.</p><p>By the end of this article, you will understand three things that shape modern frontend systems. First, what actually defines a Single Page Application beyond the buzzword. Second, why the SPA model improves responsiveness and interactivity in web applications. And third, how React enables this architecture through its rendering model and state-driven design.</p><p>This is not a tutorial about setting up React or writing components. Instead, the goal is to understand the architectural thinking behind SPAs and how React fits into that model.</p><h3><strong>The architectural shift behind modern web apps</strong></h3><p>Early websites were built around a page-based model. Each interaction triggered a request to the server, which generated a new HTML document and returned it to the browser. This worked well when the web primarily delivered content.</p><p>Modern web applications demand a different experience. Consider tools such as analytics dashboards, project management systems, or collaborative editors. Users interact continuously with the interface. Data updates frequently, UI elements move around the screen, and navigation happens rapidly.</p><p>In a traditional page-driven architecture, each of those interactions would require a server request and a full page refresh. Even small updates would rebuild the entire interface.</p><p>Single Page Applications address this limitation by shifting the responsibility for rendering the interface into the browser itself.</p><p>Instead of repeatedly requesting new pages, the browser loads the application once and then updates the interface dynamically as data changes. This change might sound simple, but it transforms the browser from a document viewer into a runtime environment for applications.</p><h3><strong>What actually defines a Single Page Application</strong></h3><p>The term &#8220;Single Page Application&#8221; can be misleading. It does not mean an application literally has only one page in the user experience. Instead, it describes how the application is delivered and rendered.</p><p>A SPA typically loads a single HTML document that acts as a container for the application. Once the application initializes, JavaScript takes responsibility for rendering and updating the interface.</p><p>From that point onward, most user interactions modify the current interface rather than loading new documents.</p><p>Several architectural patterns define this approach.</p><h4><strong>Client-side rendering</strong></h4><p>In a traditional website, the server generates HTML for each page request. In a SPA, the browser renders most of the interface.</p><p>The server still plays an important role. It provides data through APIs and delivers the initial application bundle. However, the frontend application determines how that data appears on the screen.</p><p>This allows the interface to update instantly when new data arrives.</p><h4><strong>Persistent application runtime</strong></h4><p>Because the application remains loaded in the browser, its logic persists across user interactions.</p><p>Instead of rebuilding the interface from scratch, the system modifies the existing UI based on changes in application state.</p><p>This persistence allows applications to maintain context and update small pieces of the interface without resetting the entire page.</p><h4><strong>Virtual navigation</strong></h4><p>Users still see URLs change when navigating through a SPA, but the navigation logic is handled inside the application rather than by the server.</p><p>The application interprets the URL and determines which components to display. From the user&#8217;s perspective, the experience feels like normal navigation. Internally, the browser remains on the same underlying document.</p><p>Together, these characteristics create the foundation of SPA architecture.</p><h3><strong>Why the SPA model improves responsiveness</strong></h3><p>The key advantage of SPAs is not simply that they avoid page reloads. The deeper benefit is that they reduce unnecessary work.</p><p>In a page-based system, the browser discards the entire interface whenever a new page loads. The server reconstructs the page, sends it back, and the browser renders it again.</p><p>In a SPA, the application updates only the parts of the interface that change.</p><p>Once the application code is loaded, the browser already contains everything needed to update the UI. When data changes, the system redraws only the relevant components rather than rebuilding the entire page.</p><p>This approach becomes particularly valuable in highly interactive environments.</p><p>Imagine a data dashboard where metrics update continuously while users filter results, adjust settings, and move between views. Rebuilding the entire interface for each interaction would create unnecessary delays.</p><p>SPAs allow these updates to happen immediately because the rendering logic runs locally in the browser.</p><p>However, this architecture introduces new complexity. The browser must now manage application state, UI rendering, and navigation. Without structured tools, this quickly becomes difficult to maintain.</p><p>This challenge is where frameworks such as React play an important role.</p><h3><strong>How React enables SPA architecture</strong></h3><p>React does not directly implement the SPA model. Instead, it provides a system that makes managing dynamic interfaces significantly easier.</p><p>At its core, React helps developers answer a difficult question: <em>how should the interface update when application data changes?</em></p><p>Instead of manipulating the browser DOM directly, React introduces a model where the UI is described as a function of application state.</p><p>This approach rests on two key ideas: the Virtual DOM and state-driven rendering.</p><h3><strong>The Virtual DOM and efficient UI updates</strong></h3><p>Every webpage contains a structure known as the Document Object Model, or DOM. The DOM represents the hierarchy of elements that make up the interface.</p><p>Updating the DOM directly can become expensive when applications contain large numbers of elements or frequent updates.</p><p>React addresses this problem through the Virtual DOM.</p><p>The Virtual DOM is an in-memory representation of the interface maintained by React. When application state changes, React creates a new representation of the interface and compares it with the previous version.</p><p>This comparison process determines exactly what has changed between the two states.</p><p>React then updates only those elements in the real DOM that need to change. This process is often referred to as reconciliation.</p><p>By reducing the number of direct DOM operations, React helps maintain performance even when applications grow large and complex.</p><h3><strong>State as the driver of the interface</strong></h3><p>The second important idea in React is that the interface should be driven by state.</p><p>React applications are built from components, each representing a piece of the user interface. Components maintain state that describes the data they display.</p><p>When that state changes, React automatically updates the component&#8217;s output and reconciles the differences in the DOM.</p><p>A simplified example illustrates the concept.</p><p><code>import { useState } from &#8220;react&#8221;;<br><br>function Counter() {<br>const [count, setCount] = useState(0);<br><br>return (<br>&lt;button onClick={() =&gt; setCount(count + 1)}&gt;<br>Count is {count}<br>&lt;/button&gt;<br>);<br>}</code></p><p>In this example, the interface is directly derived from the value of count. When the state changes, React recalculates the component output and updates the interface accordingly.</p><p>Developers do not manually manipulate DOM elements. Instead, they describe how the interface should look given a particular state.</p><p>This declarative model simplifies reasoning about complex interfaces. It also aligns naturally with the needs of Single Page Applications, where the interface must update frequently in response to data changes.</p><h3><strong>Why React became central to modern frontend development</strong></h3><p>React&#8217;s design aligns well with the requirements of SPA architecture.</p><p>Component-based design allows large interfaces to be broken into smaller, manageable pieces. Each component encapsulates its logic, state, and rendering behavior.</p><p>The Virtual DOM helps maintain performance by minimizing unnecessary DOM updates. Meanwhile, React&#8217;s state-driven model ensures that the interface stays synchronized with application data.</p><p>Together, these ideas provide a structured approach to managing dynamic user interfaces.</p><p>This combination of performance and developer ergonomics helped React become one of the most widely used frameworks for building modern web applications.</p><h3><strong>Final words</strong></h3><p>Single Page Applications represent a shift in how the web is used. Instead of treating the browser as a document viewer, modern applications treat it as an execution environment for complex software.</p><p>This architectural shift allows web applications to behave more like native software, delivering responsive interfaces and fluid user experiences.</p><p>Understanding SPAs means understanding three core ideas. First, the browser now handles much of the interface rendering that used to happen on the server. Second, applications persist in the browser and update the interface dynamically rather than rebuilding pages. And third, frameworks such as React provide the abstractions needed to manage the resulting complexity.</p><p>Once you view the web through this lens, many modern frontend patterns begin to make sense. Component-based architectures, state-driven rendering, and client-side routing all exist to support the same goal: building web applications that behave like real software rather than collections of pages.</p><p>These concepts are explored further in <em><strong><a href="https://www.packtpub.com/en-in/product/full-stack-react-typescript-and-node-9781803243009">Full-Stack React, TypeScript, and Node (2nd Edition)</a></strong></em>, currently available in early access for PacktPub subscribers. <em><strong><a href="https://www.amazon.com/Full-Stack-React-TypeScript-Node-applications-ebook/dp/B0DTHNT4WT/ref=sr_1_2">Preorder now!</a></strong></em></p><h1 style="text-align: center;"><strong>This Week in the News</strong></h1><ul><li><p><strong>&#128202; <a href="https://results.stateofreactnative.com/en-US/">State of React Native results are out</a></strong>: The latest State of React Native survey is live, offering a snapshot of how developers are using the framework today. It covers adoption trends, satisfaction, tooling, and common pain points across the ecosystem. Worth a look if React Native is part of your stack or roadmap.</p></li><li><p><strong>&#129302; <a href="https://x.com/dok2001/status/2026386974580330830?s=20&amp;">Cloudflare rebuilds Next.js as AI reshapes the commercial open source model</a></strong>: Cloudflare surprised the developer community this week by claiming that a single developer rewrote Next.js in just one week using AI tools, spending about $1,100 in tokens. The experiment highlights how quickly large codebases can now be recreated with AI-assisted development, raising new questions about the speed and economics of building complex frameworks.</p></li><li><p><strong>&#128200; <a href="https://github.com/vercel/next.js/issues/85470">Next.js 16 upgrade triggers unexpected request spikes</a></strong>: Some developers upgrading from Next.js 15 to 16 report higher server request volume and increased response latency. The change appears to put more strain on backend infrastructure, which could mean higher compute usage and increased hosting costs in production. A useful read if you&#8217;ve ever been surprised by a framework behaving differently outside local dev.</p></li><li><p><strong>&#128272; <a href="https://grith.ai/blog/clinejection-when-your-ai-tool-installs-another">When a GitHub Issue Becomes a Supply Chain Attack</a></strong>: A security write-up explains a vulnerability chain called <em>Clinejection</em> that exploited an AI GitHub issue bot. The attack combined prompt injection with CI cache poisoning to publish a malicious package. It&#8217;s a good reminder that AI agents in developer workflows introduce a new kind of supply chain risk.</p></li><li><p><strong>&#128172; <a href="https://vercel.com/changelog/chat-sdk">Vercel introduces the AI Chat SDK</a></strong>: Vercel has released a new Chat SDK aimed at simplifying how developers build conversational AI interfaces. The SDK provides primitives for streaming responses, handling message state, and integrating with multiple AI providers. If you&#8217;re building AI features into web apps, it removes a lot of the plumbing typically required for chat-style interactions.</p></li></ul><h1 style="text-align: center;"><strong>Beyond the Headlines</strong></h1><ul><li><p><strong>&#128260; <a href="https://gist.github.com/privatenumber/3d2e80da28f84ee30b77d53e1693378f">Migrating from TypeScript 5.x to 6.0</a>: </strong>This GitHub gist explores some extreme TypeScript type patterns that push the compiler surprisingly far. It&#8217;s a fascinating look at how conditional types, inference, and recursion turn TypeScript into something close to a compile-time programming language.</p></li><li><p><strong>&#129302; <a href="https://leodemoura.github.io/blog/2026/02/28/when-ai-writes-the-worlds-software.html">AI Is Writing More Software, but Who Checks the Output?</a></strong>: Lean creator Leo de Moura explores what happens if AI systems eventually generate the majority of production code. The essay looks beyond productivity gains and asks deeper questions about verification, correctness, and how we maintain trust in software when humans are no longer writing most of it. A thoughtful perspective on where AI-assisted development could lead.</p></li><li><p><strong>&#127902; <a href="https://www.joshwcomeau.com/animation/sprites">Web Performance with Image Sprites</a></strong>: Sprite animations are an old web technique that still works surprisingly well today. Josh Comeau walks through how sprite sheets function, how to implement them with modern CSS, and when they&#8217;re preferable to other animation approaches. A great refresher for anyone building playful UI interactions or performance-friendly animations.</p></li><li><p><strong>&#129504; <a href="https://simonwillison.net/2026/Feb/23/agentic-engineering-patterns/">Patterns for building agentic systems</a></strong>: Simon Willison breaks down emerging patterns in &#8220;agentic engineering&#8221; workflows. The article looks at how developers are structuring AI agents that can reason, call tools, and coordinate tasks across systems. If you&#8217;re experimenting with agent-style architectures, this piece highlights the design patterns that are starting to emerge.</p></li></ul><h1 style="text-align: center;"><strong>Tool of the Week</strong></h1><p>&#129513;<strong><a href="https://yoopta.dev/">Build Custom Rich Text Editors with Yoopta</a></strong></p><p>If you&#8217;re building apps that need rich text editing, finding a flexible editor can be tricky. Many solutions are either too rigid or difficult to extend.</p><p><a href="https://yoopta.dev/">Yoopta Editor</a> is a modern, open source rich text editor framework built for React. It uses a block-based architecture, making it easier to customize editing experiences, add plugins, and control how content is structured.</p><p>For developers building CMS tools, collaborative editors, or AI-assisted writing interfaces, Yoopta offers a flexible foundation without forcing a fixed editing model.</p><p><em>That&#8217;s all for this week. Have any ideas you want to see in the next article? Hit Reply!</em></p><p>Cheers!</p><p>Editor-in-chief,</p><p>Kinnari Chohan</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://packtwebdevpro.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading the <em>Web Development Newsletter </em>by Packt! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[WebDevPro #128: TypeScript Under Pressure in Evolving Full Stack Systems]]></title><description><![CDATA[Crafting the Web: Tips, Tools, and Trends for Developers]]></description><link>https://packtwebdevpro.substack.com/p/webdevpro-128-typescript-under-pressure</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/webdevpro-128-typescript-under-pressure</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Mon, 02 Mar 2026 14:02:06 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!CCCe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1><strong><a href="https://www.eventbrite.com/e/hands-on-microservices-with-spring-boot-workshop-tickets-1981982956376?aff=newsletter1">Most Spring Boot projects stop at REST APIs</a></strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://www.eventbrite.com/e/hands-on-microservices-with-spring-boot-workshop-tickets-1981982956376?aff=newsletter1" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CCCe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png 424w, https://substackcdn.com/image/fetch/$s_!CCCe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png 848w, https://substackcdn.com/image/fetch/$s_!CCCe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png 1272w, https://substackcdn.com/image/fetch/$s_!CCCe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CCCe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png" width="800" height="400" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:400,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&quot;type&quot;:null,&quot;href&quot;:&quot;https://www.eventbrite.com/e/hands-on-microservices-with-spring-boot-workshop-tickets-1981982956376?aff=newsletter1&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!CCCe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png 424w, https://substackcdn.com/image/fetch/$s_!CCCe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png 848w, https://substackcdn.com/image/fetch/$s_!CCCe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.png 1272w, https://substackcdn.com/image/fetch/$s_!CCCe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F10414b95-cb05-4109-a658-0c73b1e7d014_800x400.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>Real systems require service discovery, API gateways, centralized configuration, and built-in resilience. In this live, hands-on workshop, you&#8217;ll build a working microservices system end-to-end, define service boundaries, wire up discovery, configure a gateway, and handle failures properly.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.eventbrite.com/e/hands-on-microservices-with-spring-boot-workshop-tickets-1981982956376?aff=newsletter1&quot;,&quot;text&quot;:&quot;Get 40% off with code SAVE40&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.eventbrite.com/e/hands-on-microservices-with-spring-boot-workshop-tickets-1981982956376?aff=newsletter1"><span>Get 40% off with code SAVE40</span></a></p><div><hr></div><p>Welcome to this week&#8217;s issue of WebDevPro.</p><p>This issue looks at a common transition in modern engineering: taking a fast proof of concept and turning it into something that can survive real change.</p><p>Consider a small internal AI support chatbot. The architecture is simple. A React frontend collects messages and sends them to an Express POST /api/chat endpoint. The server returns a short reply. The goal here is speed, not durability.</p><p>To move quickly, the frontend stores messages as <em>any[]</em>. The backend reads req.body.messages from untyped JSON and returns a response like:</p><p><code>{ &#8220;reply&#8221;: &#8220;You said: hello&#8221; }</code></p><p>There is no formal contract between frontend and backend. The agreement lives in shared understanding: reply is a string, and messages is an array of objects with role and content. When both sides are written close together, this feels stable.</p><p>Then the requirements change.</p><p>The reply must now include structured data: the assistant&#8217;s message, references, and follow-up questions. The backend evolves and begins returning an object under reply instead of a string. The frontend does not change. The build passes. The browser fails at runtime because React attempts to render an object as if it were a string.</p><p>Nothing in the type system flagged the mismatch because nothing at the boundary defined what the response was supposed to be.</p><p>This is where TypeScript either acts as a safety mechanism under change or becomes a thin layer of annotations. What follows is a practical look at how that same chatbot evolves into a production-safe system by making contracts explicit and boundaries deliberate.</p><h3><strong>Phase One: Turning Assumptions into a Shared Contract</strong></h3><p>The chatbot did not break because the change was complex. It broke because the change was invisible to the type system.</p><p>On the frontend, state was typed as <em>any[]</em>. The API response was treated as whatever <em>res.json()</em> returned. On the backend, <em>req.body</em> was used without an explicit shape. From TypeScript&#8217;s perspective, there was nothing concrete to compare, so the change in response structure did not register as a problem.</p><p>The fix was not adding defensive conditionals in the UI. It was introducing a shared domain contract and making both sides depend on it.</p><p>Instead of allowing the frontend and backend to &#8220;just agree,&#8221; the system defines explicit types for:</p><ul><li><p><code>ChatMessage</code></p></li><li><p><code>ChatRequest</code></p></li><li><p><code>ChatReply</code></p></li><li><p><code>ChatResponse</code></p></li></ul><p>These types live in a shared module that both the frontend and backend import. The frontend state becomes <em>ChatMessage[]</em>. The API call returns <em>Promise&lt;ChatResponse&gt;</em>. The backend handler constructs a value that must satisfy <em>ChatResponse</em>.</p><p>At that point, the contract stops being an assumption and becomes code.</p><p>If someone changes the shape of <em>reply</em> again, the compiler will force every dependent piece of code to reconcile with that change. The mismatch that previously appeared in the browser now appears during build.</p><p>In practical terms, this shifts the feedback loop. Instead of discovering drift during manual testing or after deployment, the team discovers it the moment they try to compile. That difference seems small, but over time it fundamentally changes how safely a system can evolve.</p><h3><strong>Phase Two: Making the Network Boundary Honest</strong></h3><p>Introducing shared types stabilizes collaboration between frontend and backend. It does not solve everything.</p><p>There is still one place where untyped data enters the system: the network boundary.</p><p>On the backend, <em>req.body</em> arrives as raw JSON. On the frontend, <em>res.json()</em> returns data that TypeScript cannot inspect at runtime. Even with shared contracts, the system is still trusting external input.</p><p>In the chatbot&#8217;s case, this matters more as the system grows. Deployments may not always be perfectly synchronized. A proxy or middleware layer might alter payloads. A partial rollout could temporarily mix versions of frontend and backend.</p><p>Shared types alone cannot guard against that.</p><p>The practical adjustment is simple but important: treat boundary data as unknown until it is validated.</p><p>Instead of assuming that <em>req.body</em> matches <em>ChatRequest</em>, the backend checks that it actually does. Instead of assuming that <em>res.json()</em> returns a valid <em>ChatResponse</em>, the frontend verifies the shape before proceeding.</p><p>These checks do not need to be elaborate. Lightweight type guards are enough to confirm that required properties exist and have the correct types. Once the data passes that validation step, the rest of the system can rely on strong typing with confidence.</p><p>This introduces a clear separation of responsibilities:</p><ul><li><p>Outside the boundary, data is untrusted.</p></li><li><p>Inside the boundary, data is guaranteed to match the domain contract.</p></li></ul><p>In day to day development, this prevents subtle corruption. Rather than allowing malformed data to move deeper into the UI or business logic, the system fails immediately at the edge. Errors become explicit and local instead of diffused and harder to trace.</p><p>The chatbot remains small, but its architecture becomes more deliberate. The boundary is no longer a blind spot; it becomes a controlled entry point.</p><h3><strong>Phase Three: Containing Vendor Volatility</strong></h3><p>As the chatbot matures, another requirement arrives: support more than one LLM provider.</p><p>This is a common inflection point. Early on, it is convenient to wire the backend directly to a single SDK. The response from the provider flows straight through the server and into the UI. It feels efficient.</p><p>It also quietly couples your entire stack to a vendor&#8217;s response shape.</p><p>If that vendor changes its format, or if you decide to introduce a second provider, the ripple effects can reach the frontend quickly. What began as a backend integration detail becomes a full-stack coordination problem.</p><p>In the chatbot&#8217;s evolution, this risk is handled differently. Instead of exposing raw provider responses, the system defines a provider interface that returns a domain-level <em>ChatReply</em>. Each provider implementation adapts its own SDK response into that shared shape.</p><p>The rest of the application does not know or care which provider generated the reply. It only understands the domain contract.</p><p>This decision seems architectural, but it has very practical consequences. Switching providers or introducing a second one no longer forces a redesign of shared types. The volatility is contained. The surface area of change is smaller.</p><p>TypeScript reinforces this separation. The compiler ensures that every provider implementation produces a valid <em>ChatReply</em>. The backend handler depends on the interface, not on vendor-specific JSON.</p><p>In a growing system, this is what stability looks like. The parts that are likely to change are isolated behind clear contracts. The parts that need to remain steady, especially the frontend, are shielded from that churn.</p><h3><strong>Phase Four: Making States Explicit as Features Expand</strong></h3><p>Feature growth rarely stops at integration. The chatbot evolves again. Sometimes a response includes citations. Sometimes it does not.</p><p>A quick solution would be to add optional fields. Over time, optional fields accumulate. The type becomes flexible, but also ambiguous. It becomes unclear which combinations are valid and which are accidental.</p><p>Instead, the chatbot models these variations explicitly using a discriminated union. A response is either a plain answer or an answer with citations, and the kind field identifies which one it is.</p><p>On the frontend, rendering logic switches on that kind. The exhaustive check ensures that every variant is handled.</p><p>This design choice has a subtle but important effect. When a new response variant is introduced later, the compiler highlights every place that must adapt. Nothing slips through unnoticed.</p><p>In everyday development, this reduces the risk of partial updates. The type system becomes a guide for refactoring, not just a static annotation layer.</p><p>The chatbot still feels small. The difference is that its possible states are no longer implied. They are declared.</p><h3><strong>Phase Five: Removing Quiet Type Erosion</strong></h3><p>As the chatbot grows, new endpoints appear. Health checks. Admin actions. Maybe analytics or feedback capture. The API surface expands gradually.</p><p>This is usually where small shortcuts start accumulating.</p><p>A common one looks harmless:</p><p><code>const data = (await res.json()) as ChatResponse;</code></p><p>The cast makes the compiler quiet. It also shifts responsibility back to the developer. At the exact point where the system is most exposed to incorrect data, you are asserting that everything is fine.</p><p>In a small codebase, this feels manageable. In a growing one, these assertions multiply. Over time, they erode the safety you thought TypeScript was providing.</p><p>In the chatbot&#8217;s evolution, this problem is addressed structurally rather than procedurally. Instead of scattering casts, the system defines a mapping between route literals and their request and response types. The endpoint determines the shape. The generic client enforces it.</p><p>Now the type of<em> /api/chat </em>is tied directly to <em>ChatRequest</em> and <em>ChatResponse</em>. You cannot accidentally call the wrong endpoint and pretend it returns something else. The compiler resolves the relationship based on the route itself.</p><p>This removes a category of silent drift. It also makes the API surface self-documenting. When someone adds a new endpoint, they define its contract in one place, and the rest of the system aligns automatically.</p><p>It is a small shift in structure, but it prevents gradual type erosion.</p><h3><strong>What This Evolution Actually Achieved</strong></h3><p>The chatbot still answers questions. The UI still renders messages. The architecture is not radically different from the initial proof of concept.</p><p>What changed is where mistakes surface.</p><p>At first, mismatches appeared in the browser.<br>After shared contracts, they appeared during compilation.<br>After boundary validation, they appeared at the edge of the system.<br>After isolating providers, vendor changes stopped leaking across layers.<br>After modeling variants explicitly, feature growth became safer.<br>After tightening endpoint typing, unsafe assumptions stopped spreading quietly.</p><p>None of these changes required advanced language features. They required clarity about boundaries and discipline about contracts.</p><p>In a system that evolves under real-world pressure, assumptions are the most fragile dependency. TypeScript is most valuable when it turns those assumptions into enforceable structure.</p><p>The chatbot did not become more sophisticated for its own sake. It became more predictable under change.</p><p>For a deeper exploration, pre-order <em><strong><a href="https://www.amazon.com/Clean-Code-Typescript-TypeScript-production-ready-ebook/dp/B0F9YGLK2L">Clean Code with TypeScript</a></strong></em>. The book takes a detailed look at the evolving chatbot system and walks through the architectural decisions, trade-offs, and production considerations behind it.</p><p>If you&#8217;re a PacktPub subscriber, you can access the Early Access version right away.</p><h1><strong>This Week in the News</strong></h1><ul><li><p><strong>&#9729;&#65039; <a href="https://blog.cloudflare.com/vinext/">Cloudflare rebuilds Next.js on Vite</a></strong>: Cloudflare unveiled <strong><a href="https://github.com/cloudflare/vinext">vinext</a></strong>, an experimental reimplementation of the Next.js API surface built on Vite, reportedly put together in a week using AI coding agents and the official Next.js test suite as a spec. Instead of adapting Next&#8217;s build output for non-Vercel platforms, Cloudflare rebuilt the framework layer itself to make deployment on its infrastructure more natural. vinext already supports routing, SSR, React Server Components, server actions, middleware, and both routing systems, passing about 94 percent of the Next 16 test suite. Cloudflare claims faster builds and smaller client bundles in early benchmarks, while calling the results directional. It is still early, but this is a bold signal in the ongoing platform versus framework conversation.</p></li><li><p>&#127344;&#65039; <strong><a href="https://github.com/analogjs/angular-skills">Angular Skills for coding agents</a></strong>: Angular developers can now equip their coding agents with &#8220;Angular Skills,&#8221; a set of curated defaults and patterns designed to guide agents toward modern Angular best practices. The project packages conventions, structure, and tooling preferences so AI-assisted workflows generate code that feels aligned with today&#8217;s Angular ecosystem. Do agent skills materially improve output quality? That remains to be seen. At the very least, they formalize standards and make human intent more explicit, which may be half the battle in AI-assisted development.</p></li><li><p><strong>&#128994;<a href="https://github.com/nodejs/node/releases/tag/v24.14.0">Node.js 24.14.0 LTS</a> and <a href="https://github.com/nodejs/node/releases/tag/v25.7.0">25.7.0 Current released</a></strong>: Node shipped both an LTS and a Current release this week, and this one is more than routine version churn. The LTS update tightens up async_hooks, improves fs.watch reliability, adds proxy configuration support, and begins exposing early ESM embedder API enhancements. If you&#8217;re running backend services, SSR stacks, or dev tooling that leans on Node internals, these changes are practical, not cosmetic. Meanwhile, 25.7.0 Current gives a preview of where the runtime is heading. Framework maintainers and teams with native modules should treat this as a signal to test early and avoid CI surprises later.</p></li><li><p><strong>&#128200; <a href="https://openclaw.report/news/openclaw-overtakes-python-linux-github">OpenClaw briefly overtakes Python projects on GitHub</a></strong>: A retro game reimplementation project saw a spike in GitHub activity that temporarily outranked major Python repositories. While largely a trend metric, this serves as a reminder that GitHub stars and ranking spikes do not always reflect lasting ecosystem impact. For developers, this is a useful gut check. Popularity metrics can highlight energy, but they don&#8217;t always indicate production relevance or long-term impact.</p></li><li><p><strong>&#129302; <a href="https://www.theverge.com/ai-artificial-intelligence/883243/anthropic-claude-deepseek-china-ai-distillation">Claude Code turns one as distillation dispute surfaces</a></strong>: Anthropic marked the <a href="https://x.com/bcherny/status/2025701404988592359">first anniversary of Claude Code</a> while raising concerns about competitors using Claude outputs to train rival models through large-scale distillation. The discussion moves beyond company rivalry and into deeper questions around model output ownership, competitive boundaries, and how AI tooling companies protect their work. For developers building AI-powered products, this matters. The ecosystem is still defining what is acceptable reuse, what is extraction, and where legal lines will be drawn. Tooling decisions today are increasingly shaped by these policy and governance shifts</p></li><li><p><strong>&#127963;&#65039; <a href="https://react.dev/blog/2026/02/24/the-react-foundation">React moves to the Linux Foundation</a></strong>: React and React Native are now governed by a newly formed React Foundation under the Linux Foundation. This shifts stewardship from a single corporate sponsor to neutral, open governance. For teams betting their front end architecture on React, this reduces long-term platform risk. Governance stability may not feel urgent in daily development, but it quietly shapes the future of roadmaps, community trust, and ecosystem continuity.</p></li></ul><h1><strong>Beyond the Headlines</strong></h1><ul><li><p><strong>&#129408; <a href="https://ladybird.org/posts/adopting-rust/">Ladybird adopts Rust for new components</a>: </strong>The Ladybird browser project is moving new development to Rust, citing safety and maintainability. This isn&#8217;t just about language preference. It reflects the industry&#8217;s steady migration toward memory-safe systems programming in infrastructure-level code. The browser space has historically been C and C++. Rust&#8217;s continued expansion here signals that safety is becoming a baseline expectation, not a luxury.</p></li><li><p>&#129302; <strong><a href="https://kanyilmaz.me/2026/02/19/five-stages-of-ai-agents.html">The five stages of AI agents</a></strong>: A useful framework is emerging around how AI agents evolve: from basic task automation to more autonomous, goal-oriented systems. For developers experimenting with AI workflows, this gives structure to what can otherwise feel like hype. The takeaway is simple. Not every workflow needs autonomy. Understanding where your system sits on that spectrum prevents overengineering and keeps expectations grounded.</p></li><li><p>&#129504; <strong><a href="https://mitchellh.com/writing/my-ai-adoption-journey">Mitchell Hashimoto on AI adoption</a></strong>: Mitchell Hashimoto, the co-founder of HashiCorp shared a candid look at integrating AI tools into his workflow. Not evangelism. Not backlash. Just a practical breakdown of where AI speeds things up and where it still falls short. That grounded middle space is where most developers are operating right now. AI is useful. It is not magic. And thoughtful integration beats blanket adoption.</p><div><hr></div></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://www.eventbrite.com/e/safely-refactor-production-codebases-with-ai-registration-1982005923070?aff=webdevpro" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!j4fT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4155d47e-b1d4-4060-a3d5-c83948328948_1920x960.png 424w, https://substackcdn.com/image/fetch/$s_!j4fT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4155d47e-b1d4-4060-a3d5-c83948328948_1920x960.png 848w, https://substackcdn.com/image/fetch/$s_!j4fT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4155d47e-b1d4-4060-a3d5-c83948328948_1920x960.png 1272w, https://substackcdn.com/image/fetch/$s_!j4fT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4155d47e-b1d4-4060-a3d5-c83948328948_1920x960.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!j4fT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4155d47e-b1d4-4060-a3d5-c83948328948_1920x960.png" width="1456" height="728" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4155d47e-b1d4-4060-a3d5-c83948328948_1920x960.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:728,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&quot;type&quot;:null,&quot;href&quot;:&quot;https://www.eventbrite.com/e/safely-refactor-production-codebases-with-ai-registration-1982005923070?aff=webdevpro&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!j4fT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4155d47e-b1d4-4060-a3d5-c83948328948_1920x960.png 424w, https://substackcdn.com/image/fetch/$s_!j4fT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4155d47e-b1d4-4060-a3d5-c83948328948_1920x960.png 848w, https://substackcdn.com/image/fetch/$s_!j4fT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4155d47e-b1d4-4060-a3d5-c83948328948_1920x960.png 1272w, https://substackcdn.com/image/fetch/$s_!j4fT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4155d47e-b1d4-4060-a3d5-c83948328948_1920x960.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>Refactoring production systems is risky, especially when API changes and hidden coupling are involved. In this Deep Engineering session, learn how to safely evolve real-world codebases using ast-grep and Claude Code, with practical guardrails you can apply immediately.</p><p>Use code <strong><a href="https://www.eventbrite.com/e/safely-refactor-production-codebases-with-ai-registration-1982005923070?aff=webdevpro">WDP40</a></strong> to get <strong><a href="https://www.eventbrite.com/e/safely-refactor-production-codebases-with-ai-registration-1982005923070?aff=webdevpro">40% off</a></strong> your seat.</p><div><hr></div><h1><strong>Tool of the Week</strong></h1><p><strong>&#128737;&#65039; <a href="https://zod.dev/">Zod Makes Runtime Validation Feel Native to TypeScript</a></strong></p><p>If you&#8217;ve ever trusted <code>req.body</code><em> </em>a little too much or written <code>as SomeType</code> just to quiet the compiler, you already know the pain: TypeScript disappears at runtime. The type system keeps you safe inside your codebase, but JSON at the network boundary remains unchecked.</p><p>Zod solves that gap cleanly. It&#8217;s a TypeScript-first schema validation library that lets you define runtime validation and static types in one place. You describe the shape once, validate incoming data against it, and automatically infer the TypeScript type. No duplication. No drift between interface and validator.</p><p>The real value shows up under change. When your API evolves or a provider shifts its response format, Zod forces the mismatch to surface immediately at the boundary instead of leaking deeper into your system. It turns assumptions into enforced contracts.</p><p>Good architecture is often about making edges explicit. Zod gives those edges structure.</p><p><em>That&#8217;s all for this week. Have any ideas you want to see in the next article? Hit Reply!</em></p><p>Cheers!</p><p>Editor-in-chief,</p><p>Kinnari Chohan</p>]]></content:encoded></item><item><title><![CDATA[WebDevPro #127
Design Patterns as Decision Frameworks, Not Recipes]]></title><description><![CDATA[Crafting the Web: Tips, Tools, and Trends for Developers]]></description><link>https://packtwebdevpro.substack.com/p/webdevpro-127-design-patterns-as</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/webdevpro-127-design-patterns-as</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Mon, 23 Feb 2026 14:03:10 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!xSSB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5b59ac-7716-4b49-a8fa-2ce5be38a4c9_1024x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1><strong><a href="https://getunblocked.com/?utm_source=packt_webdevpro&amp;utm_medium=email&amp;utm_campaign=contextengine&amp;utm_content=260223_primary">Unblocked: The context layer your AI tools are missing</a></strong></h1><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xSSB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5b59ac-7716-4b49-a8fa-2ce5be38a4c9_1024x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xSSB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5b59ac-7716-4b49-a8fa-2ce5be38a4c9_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!xSSB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5b59ac-7716-4b49-a8fa-2ce5be38a4c9_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!xSSB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5b59ac-7716-4b49-a8fa-2ce5be38a4c9_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!xSSB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5b59ac-7716-4b49-a8fa-2ce5be38a4c9_1024x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xSSB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5b59ac-7716-4b49-a8fa-2ce5be38a4c9_1024x1024.png" width="218" height="218" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/eb5b59ac-7716-4b49-a8fa-2ce5be38a4c9_1024x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1024,&quot;width&quot;:1024,&quot;resizeWidth&quot;:218,&quot;bytes&quot;:837736,&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://packtwebdevpro.substack.com/i/188883127?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5b59ac-7716-4b49-a8fa-2ce5be38a4c9_1024x1024.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_!xSSB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5b59ac-7716-4b49-a8fa-2ce5be38a4c9_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!xSSB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5b59ac-7716-4b49-a8fa-2ce5be38a4c9_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!xSSB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5b59ac-7716-4b49-a8fa-2ce5be38a4c9_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!xSSB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feb5b59ac-7716-4b49-a8fa-2ce5be38a4c9_1024x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>Give your agents the understanding they need to generate reliable code, reviews, and answers. Unblocked builds context from your team&#8217;s code, PR history, conversations, documentation, planning tools, and runtime signals. It surfaces the insights that matter so AI outputs reflect how your system actually works.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://getunblocked.com/?utm_source=packt_webdevpro&amp;utm_medium=email&amp;utm_campaign=contextengine&amp;utm_content=260223_primary&quot;,&quot;text&quot;:&quot;See how it works&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://getunblocked.com/?utm_source=packt_webdevpro&amp;utm_medium=email&amp;utm_campaign=contextengine&amp;utm_content=260223_primary"><span>See how it works</span></a></p><div><hr></div><p>Welcome to this week&#8217;s issue of WebDevPro.</p><p>If you&#8217;ve been building and maintaining systems for a while, you&#8217;ve probably felt the friction that doesn&#8217;t show up in code reviews.</p><p>And here&#8217;s something that doesn&#8217;t get said often enough:<em><strong> most engineering pain isn&#8217;t caused by bad code. It&#8217;s caused by unexamined decisions.</strong></em></p><p>Nobody deliberately optimizes for rigidity. Nobody sets out to make performance worse or future changes harder. But when trade-offs aren&#8217;t made explicit, that&#8217;s exactly where teams end up.</p><p>You notice it when:</p><ul><li><p>A small requirement change forces a wide refactor</p></li><li><p>A performance issue appears under load and the root cause isn&#8217;t obvious</p></li><li><p>&#8220;Best practice&#8221; debates stall because everyone is arguing from instinct, not intent</p></li></ul><p>We&#8217;re often handed rules like these:</p><ul><li><p>Use strict equality</p></li><li><p>Avoid blocking I/O</p></li><li><p>Prefer Map over Object</p></li><li><p>Use Set for deduplication</p></li><li><p>Be careful with parseInt</p></li></ul><p>These guidelines are useful, especially early on. They prevent common mistakes.</p><p>But over time, following rules without understanding the trade-offs turns into habit, not judgment.</p><p><strong>This week&#8217;s issue looks at patterns differently. Not as templates to apply or badges of clean code, but as decision frameworks.</strong></p><p>By the end of this article, you&#8217;ll start seeing what a piece of code is really optimizing for, notice the hidden costs behind everyday implementation choices, think more deliberately about where change should happen, and reframe conversations from &#8220;Is this correct?&#8221; to &#8220;What are we trading off?&#8221;</p><p>That shift from applying rules to making deliberate trade-offs is where engineering starts to feel intentional.</p><p>And that&#8217;s what we&#8217;re unpacking today.</p><h3><strong>Code Shape and the Cost of Change</strong></h3><p>Most problematic code works. That&#8217;s why it survives.</p><p><code>createUser(name, email, password, phoneNumber, role = &#8216;guest&#8217;)</code></p><p>There&#8217;s nothing obviously wrong here. Until the domain changes.</p><p>Add a required field.<br>Deprecate one parameter.<br>Split roles into multiple variants.</p><p>Now you&#8217;re updating dozens of call sites and hoping argument order wasn&#8217;t misused somewhere. Switching to object parameters:</p><p><code>createUser({ name, email, password, phoneNumber, role = &#8216;guest&#8217; })</code></p><p>This changes what the API optimizes for. Specifically, order stops mattering, adding fields becomes safer, and call sites become self-documenting.</p><p>This is design thinking at the function level. You&#8217;re choosing a shape that absorbs change instead of amplifying it.</p><h3><strong>Hidden Transformations and Predictability</strong></h3><p>Loose equality in JavaScript produces results that surprise people:</p><p><code>false == 0 // true</code></p><p><code>&#8216;&#8217; == false // true</code></p><p><code>[] == false // true</code></p><p>These aren&#8217;t bugs; they follow the language&#8217;s coercion rules.</p><p>The issue is that the conversion happens implicitly. When a comparison behaves unexpectedly, it looks like a logic error, not a type conversion chain.</p><p>Using === keeps comparisons explicit. It removes hidden work.</p><p>Parsing has similar edges.</p><p><code>parseInt(0.0000005) // 5</code></p><p>parseInt converts its input to a string, then parses from the start until it hits an invalid character. A number like 0.0000005 may be represented as &#8220;5e-7&#8221;, so parsing stops at &#8220;e&#8221;.</p><p>This is documented behavior. The problem isn&#8217;t the function. It&#8217;s assuming there are no intermediate transformations.</p><p><strong>The broader lesson</strong>: implicit conversions reduce clarity. When behavior depends on hidden steps, bugs become harder to reason about.</p><h3><strong>Runtime Reality: Blocking Work and Delegation</strong></h3><p>Node.js executes JavaScript on a single main thread that drives the event loop. CPU-heavy synchronous code blocks that thread. While it runs, nothing else progresses.</p><p>That&#8217;s why synchronous work in request handlers can reduce throughput and increase latency under load.</p><p>Asynchronous APIs often help because some operations can be delegated to the system or to worker threads (for example, many crypto operations have asynchronous variants). The main thread remains free to coordinate.</p><p>But async alone doesn&#8217;t solve architectural problems.</p><p>Performance often improves more by reducing how often expensive work runs than by simply changing it to async. Caching, batching, and eliminating redundant computation frequently have a bigger impact than switching APIs.</p><p>The real pattern isn&#8217;t &#8220;async good, sync bad.&#8221; It&#8217;s understanding where your runtime is serial and designing accordingly.</p><h3><strong>Data Structures as Cost Models</strong></h3><p>Choosing between Object, Map, Array, and Set is about workload and not preference. Objects fit well when:</p><ul><li><p>keys are known and stable</p></li><li><p>you&#8217;re modeling record-like data</p></li><li><p>JSON serialization matters</p></li></ul><p>Maps fit well when:</p><ul><li><p>keys are dynamic</p></li><li><p>frequent insertions and deletions occur</p></li><li><p>iteration order must be preserved</p></li><li><p>non-string keys are required</p></li></ul><p>Arrays excel at ordered data and transformations. Sets excel at uniqueness and fast membership checks.<br>No structure is universally better. Each implies a different cost model. When you align structure with usage patterns, the code becomes simpler and more predictable.</p><h3><strong>Classic Patterns: Controlling Where Change Happens</strong></h3><p>Design patterns get introduced as diagrams. Boxes, arrows, interfaces. In practice, nobody reaches for Strategy because they love abstractions. They reach for it because some piece of logic keeps changing and it&#8217;s starting to infect everything around it. Pricing rules change. Validation rules change. Feature flags change. If that logic is scattered across the system, every update becomes a small cleanup project.</p><p>Strategy just gives that volatility a place to live.</p><p>Observer shows up when components are getting too aware of each other. One module updates something and suddenly three others need to react. Hard-coded calls turn into a web of dependencies. Events or observers aren&#8217;t about elegance. They&#8217;re about reducing how much each part needs to know.</p><p>Adapter is what you write when an external API doesn&#8217;t quite fit your model, and you don&#8217;t want your entire codebase shaped by someone else&#8217;s decisions. It&#8217;s a boundary. A buffer.</p><p>None of these patterns are impressive on their own. What they&#8217;re really doing is controlling where change hurts.</p><p>They add indirection, yes. That indirection costs something. But in return, you stop paying interest every time requirements shift. That&#8217;s the trade.</p><h3><strong>Containment Over Cleverness</strong></h3><p>There&#8217;s always a moment when modifying a prototype feels like a clever shortcut.</p><p>You add a helper to Array.prototype so you don&#8217;t have to import a utility everywhere. You tweak Object.prototype to normalize something globally. It works. It even feels elegant.</p><p>The catch is that you&#8217;ve quietly changed the rules for the entire runtime.</p><p>Now every array in the system has that extra method. Every object inherits the behavior whether it asked for it or not. If something breaks, the failure won&#8217;t point back to your &#8220;nice little improvement.&#8221; It&#8217;ll surface somewhere unrelated, and debugging it will take longer than the shortcut saved.</p><p>In small scripts, this might be fine. In shared codebases, libraries, or long-lived services, it&#8217;s a different story. The blast radius is bigger than it looks.</p><p>Most engineers grow out of this not because someone tells them it&#8217;s wrong, but because they&#8217;ve spent a day tracing a bug back to a global modification they forgot existed.</p><p>After that, containment starts to feel a lot more attractive than cleverness.</p><h3><strong>Final words: Making Trade-offs Explicit</strong></h3><p>The deepest anti-pattern isn&#8217;t picking the &#8220;wrong&#8221; API but rather building for neatness today in places that are guaranteed to change later.</p><p>That&#8217;s why patterns matter. Not because they&#8217;re clever, but because they force the trade-offs into the open:</p><ul><li><p>CPU vs latency</p></li><li><p>memory vs speed</p></li><li><p>coupling vs flexibility</p></li><li><p>simplicity now vs adaptability later</p></li></ul><p>Used like recipes, patterns turn rigid fast. Used like decision frameworks, they do something much more valuable: they make teams talk about consequences instead of preferences.</p><p>You spend less time arguing about &#8220;best practices,&#8221; and more time agreeing on what kind of system you&#8217;re actually building.</p><p>That&#8217;s the shift from following rules to developing engineering judgment.</p><h1><strong>This Week in the News</strong></h1><ul><li><p><strong>&#129513;<a href="https://devblogs.microsoft.com/typescript/announcing-typescript-6-0-beta/">TypeScript 6.0 Beta Is Here and 7.0 Will Change More Than You Think</a></strong>: TypeScript 6.0 is now in beta and while it looks like a transitional release, it lays the groundwork for the Go-based TypeScript 7. Some changes may subtly affect existing projects, especially around deprecated behaviors and internal shifts. This is the release to test against early so you are not caught off guard when 7.0 lands with deeper architectural changes.</p></li><li><p><strong>&#127760; <a href="https://developer.chrome.com/blog/webmcp-epp">WebMCP and EPP Show Where Chrome Wants the Web to Go Next</a></strong>: With WebMCP and EPP, Chrome is exploring structured communication between web apps and external processes. This could reshape how developer tools, AI agents, and browser-based apps coordinate capabilities. If you care about automation-heavy workflows or AI-assisted development, this signals where the platform is heading.</p></li><li><p><strong>&#128279; <a href="https://github.blog/changelog/2026-02-18-npm-bulk-trusted-publishing-config-and-script-security-now-generally-available/">npm Just Made Supply Chain Security Harder to Ignore</a></strong>: npm 11.10.0 rolls out bulk trusted publishing configuration and stronger lifecycle script protections. Teams managing multiple packages can now streamline trusted publishing, while script security improvements reduce risk from malicious or unexpected install-time behavior. Worth reading if you maintain libraries or ship production packages regularly.</p></li><li><p><strong>&#128736;&#65039; <a href="https://webkit.org/blog/17818/announcing-interop-2026/">Interop 2026 Aims to Remove More Cross Browser Headaches</a></strong>: Interop is a yearly cross-browser effort where engine teams align on specific platform features and work together to close gaps in behavior and support. Interop 2026 is now announced, continuing the collaboration between WebKit, Chromium, and Gecko with a fresh set of focus areas. For developers, it is one of the most reliable signals of which web platform fixes are actually likely to land across all major browsers.</p></li></ul><h1><strong>Beyond the Headlines</strong></h1><ul><li><p><strong>&#9889;<a href="https://www.repoflow.io/blog/node-js-vs-deno-vs-bun-performance-benchmarks">Node vs Deno vs Bun Benchmarks Show Where the Real Gaps Are</a>: </strong>Fresh performance benchmarks compare Node.js, Deno, and Bun across real-world scenarios rather than synthetic micro tests. The results challenge a few common assumptions about which runtime is &#8220;fastest&#8221; and where that speed actually matters. Worth reading before you make runtime decisions based purely on hype or benchmark screenshots.</p></li><li><p><strong>&#129504; <a href="https://shud.in/thoughts/performance-is-not-a-technical-problem">Performance Is Not a Technical Problem</a></strong>: This essay argues that most performance issues stem from priorities, incentives, and product decisions rather than raw engineering limits. It reframes optimization as a cultural and organizational question, not just a profiling exercise. A sharp perspective shift for anyone working on growing codebases where &#8220;we&#8217;ll fix it later&#8221; keeps winning.</p></li><li><p><strong>&#9823;&#65039;<a href="https://simonwillison.net/2026/Feb/15/deep-blue/">What Deep Blue Still Teaches Us About AI Hype</a></strong>: Simon Willison revisits IBM&#8217;s Deep Blue moment and connects it to today&#8217;s AI narratives. The piece explores how milestone victories shape public perception, funding, and expectations long after the headlines fade. A thoughtful read for developers navigating the current AI wave and trying to separate signal from spectacle.</p></li><li><p><strong>&#129525; <a href="https://nodejsdesignpatterns.com/blog/nodejs-http-request/">HTTP in Node.js Gets Tricky Fast and This Guide Explains Why</a></strong>: Making an HTTP request in Node.js looks simple until you hit retries, timeouts, streaming, backpressure, and error handling in real production code. This deep dive breaks down the patterns that help you move beyond quick fixes and build request logic that stays reliable under load. It&#8217;s also a great preview of the thinking behind <em><a href="https://www.amazon.com/Node-js-Design-Patterns-production-grade-applications/dp/1803238941">Node.js Design Patterns</a></em>, one of the most practical books for developers building serious Node.js systems.</p></li></ul><h1><strong>Tool of the Week</strong></h1><p><strong>&#129518; <a href="https://github.com/qax-os/excelize">Excelize Makes Spreadsheet Automation in Go Feel Like a Superpower</a></strong></p><p>If you&#8217;ve ever had to generate Excel reports, clean up spreadsheets, or build export pipelines, you already know the pain: most tooling is either fragile or wildly overcomplicated. <strong>Excelize, </strong>built by <strong><a href="https://www.linkedin.com/in/xurime/">Ri Xu</a> </strong>is an open-source Go library that makes working with real .xlsx files feel straightforward, from formatting and formulas to charts and large-file handling.</p><p>The most interesting part is the story behind it. The <a href="https://theparallelstack.substack.com/p/building-excelize-with-creator-xu">write-up on how Excelize was built</a> shows what it takes to make &#8220;boring&#8221; infrastructure reliable: handling OpenXML edge cases, keeping the API Go-friendly, and evolving features without breaking existing users. It&#8217;s a strong example of how long-term OSS gets built, one painful spreadsheet at a time.</p><p>Good developer tooling rarely starts as &#8220;let&#8217;s build a library.&#8221; It starts as &#8220;this keeps hurting, let&#8217;s fix it properly.&#8221; Excelize is the result of sticking with that fix long enough to turn it into real infrastructure.</p><p><em>That&#8217;s all for this week. Have any ideas you want to see in the next article? Hit Reply!</em></p><p>Cheers!</p><p>Editor-in-chief,</p><p>Kinnari Chohan</p><div><hr></div><p>Brought to you in cooperation with <strong><a href="https://getunblocked.com/?utm_source=packt_webdevpro&amp;utm_medium=email&amp;utm_campaign=contextengine&amp;utm_content=260223_primary">Unblocked</a></strong>:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5NnA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ec4224-abfb-482a-b388-d4a9d72042ec_8042x1737.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5NnA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ec4224-abfb-482a-b388-d4a9d72042ec_8042x1737.png 424w, https://substackcdn.com/image/fetch/$s_!5NnA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ec4224-abfb-482a-b388-d4a9d72042ec_8042x1737.png 848w, https://substackcdn.com/image/fetch/$s_!5NnA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ec4224-abfb-482a-b388-d4a9d72042ec_8042x1737.png 1272w, https://substackcdn.com/image/fetch/$s_!5NnA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ec4224-abfb-482a-b388-d4a9d72042ec_8042x1737.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5NnA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ec4224-abfb-482a-b388-d4a9d72042ec_8042x1737.png" width="280" height="60.38461538461539" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/93ec4224-abfb-482a-b388-d4a9d72042ec_8042x1737.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:314,&quot;width&quot;:1456,&quot;resizeWidth&quot;:280,&quot;bytes&quot;:174076,&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://packtwebdevpro.substack.com/i/188883127?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ec4224-abfb-482a-b388-d4a9d72042ec_8042x1737.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_!5NnA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ec4224-abfb-482a-b388-d4a9d72042ec_8042x1737.png 424w, https://substackcdn.com/image/fetch/$s_!5NnA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ec4224-abfb-482a-b388-d4a9d72042ec_8042x1737.png 848w, https://substackcdn.com/image/fetch/$s_!5NnA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ec4224-abfb-482a-b388-d4a9d72042ec_8042x1737.png 1272w, https://substackcdn.com/image/fetch/$s_!5NnA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93ec4224-abfb-482a-b388-d4a9d72042ec_8042x1737.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://packtwebdevpro.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Web Development Newsletter by Packt! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[WebDevPro #126: Using AI in Development Without Losing Architectural Control]]></title><description><![CDATA[Crafting the Web: Tips, Tools, and Trends for Developers]]></description><link>https://packtwebdevpro.substack.com/p/webdevpro-126-using-ai-in-development</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/webdevpro-126-using-ai-in-development</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Mon, 16 Feb 2026 14:02:37 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!-Epb!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c609e43-4006-496a-9adf-84620ff6b584_500x500.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div><hr></div><h1><strong><a href="https://links.uk.defend.egress.com/Warning?crId=697b625161078799765e2b2b&amp;Domain=packt.com&amp;Threat=eNpzrShJLcpLzAEADmkDRA%3D%3D&amp;Lang=en&amp;Base64Url=eNpNTjsOwjAMvQ2bGxYWpIqjRK5jqEVTR4nTiNtjEAPj-7_VrLRrCGOMyXjjKs-JNIfBi-xYW0h8UMW7BRS4awXHvGnh2mDVAaaAtIqTgHA5gwvEu0GpmjqZHGIvWFSb3brlmDlJzzOVfPrApt3ts495rUe-JGEuKI99ThZR4n9T_N2Ki5ge8gbF6Umj&amp;@OriginalLink=www.telerik.com">Webinar: How to Build Faster with AI Agents</a></strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://links.uk.defend.egress.com/Warning?crId=697b625161078799765e2b2b&amp;Domain=packt.com&amp;Threat=eNpzrShJLcpLzAEADmkDRA%3D%3D&amp;Lang=en&amp;Base64Url=eNpNTjsOwjAMvQ2bGxYWpIqjRK5jqEVTR4nTiNtjEAPj-7_VrLRrCGOMyXjjKs-JNIfBi-xYW0h8UMW7BRS4awXHvGnh2mDVAaaAtIqTgHA5gwvEu0GpmjqZHGIvWFSb3brlmDlJzzOVfPrApt3ts495rUe-JGEuKI99ThZR4n9T_N2Ki5ge8gbF6Umj&amp;@OriginalLink=www.telerik.com" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cCeU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73a597bb-5eda-4230-875c-e72e45057d96_858x267.png 424w, https://substackcdn.com/image/fetch/$s_!cCeU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73a597bb-5eda-4230-875c-e72e45057d96_858x267.png 848w, https://substackcdn.com/image/fetch/$s_!cCeU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73a597bb-5eda-4230-875c-e72e45057d96_858x267.png 1272w, https://substackcdn.com/image/fetch/$s_!cCeU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73a597bb-5eda-4230-875c-e72e45057d96_858x267.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cCeU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73a597bb-5eda-4230-875c-e72e45057d96_858x267.png" width="858" height="267" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/73a597bb-5eda-4230-875c-e72e45057d96_858x267.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:267,&quot;width&quot;:858,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:&quot;https://links.uk.defend.egress.com/Warning?crId=697b625161078799765e2b2b&amp;Domain=packt.com&amp;Threat=eNpzrShJLcpLzAEADmkDRA%3D%3D&amp;Lang=en&amp;Base64Url=eNpNTjsOwjAMvQ2bGxYWpIqjRK5jqEVTR4nTiNtjEAPj-7_VrLRrCGOMyXjjKs-JNIfBi-xYW0h8UMW7BRS4awXHvGnh2mDVAaaAtIqTgHA5gwvEu0GpmjqZHGIvWFSb3brlmDlJzzOVfPrApt3ts495rUe-JGEuKI99ThZR4n9T_N2Ki5ge8gbF6Umj&amp;@OriginalLink=www.telerik.com&quot;,&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="" srcset="https://substackcdn.com/image/fetch/$s_!cCeU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73a597bb-5eda-4230-875c-e72e45057d96_858x267.png 424w, https://substackcdn.com/image/fetch/$s_!cCeU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73a597bb-5eda-4230-875c-e72e45057d96_858x267.png 848w, https://substackcdn.com/image/fetch/$s_!cCeU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73a597bb-5eda-4230-875c-e72e45057d96_858x267.png 1272w, https://substackcdn.com/image/fetch/$s_!cCeU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73a597bb-5eda-4230-875c-e72e45057d96_858x267.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>Learn how full&#8209;stack developers boost productivity by 50% with AI agents that automate layout, styling, and component generation through RAG and LLM pipelines. See how orchestration and spec&#8209;driven workflows keep you in control of quality and consistency.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://links.uk.defend.egress.com/Warning?crId=697b625161078799765e2b2b&amp;Domain=packt.com&amp;Threat=eNpzrShJLcpLzAEADmkDRA%3D%3D&amp;Lang=en&amp;Base64Url=eNpNTjsOwjAMvQ2bGxYWpIqjRK5jqEVTR4nTiNtjEAPj-7_VrLRrCGOMyXjjKs-JNIfBi-xYW0h8UMW7BRS4awXHvGnh2mDVAaaAtIqTgHA5gwvEu0GpmjqZHGIvWFSb3brlmDlJzzOVfPrApt3ts495rUe-JGEuKI99ThZR4n9T_N2Ki5ge8gbF6Umj&amp;@OriginalLink=www.telerik.com&quot;,&quot;text&quot;:&quot;Save your seat&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://links.uk.defend.egress.com/Warning?crId=697b625161078799765e2b2b&amp;Domain=packt.com&amp;Threat=eNpzrShJLcpLzAEADmkDRA%3D%3D&amp;Lang=en&amp;Base64Url=eNpNTjsOwjAMvQ2bGxYWpIqjRK5jqEVTR4nTiNtjEAPj-7_VrLRrCGOMyXjjKs-JNIfBi-xYW0h8UMW7BRS4awXHvGnh2mDVAaaAtIqTgHA5gwvEu0GpmjqZHGIvWFSb3brlmDlJzzOVfPrApt3ts495rUe-JGEuKI99ThZR4n9T_N2Ki5ge8gbF6Umj&amp;@OriginalLink=www.telerik.com"><span>Save your seat</span></a></p><div><hr></div><p>Welcome to this week&#8217;s issue of WebDevPro.</p><p>If you&#8217;ve written any meaningful amount of code recently, AI is already part of your workflow. It finishes your lines, scaffolds components, suggests refactors, and removes a lot of the friction from day-to-day implementation. At the same time, more teams are shipping AI-powered capabilities directly into their products.</p><p>The productivity gains are real. Development moves faster. Experimentation becomes easier.</p><p>But speed introduces a structural question that doesn&#8217;t get talked about enough. When implementation becomes this easy, AI can start shaping architecture by default. Not through dramatic failures, but through small decisions that slip in unnoticed. A suggestion becomes a pattern. A pattern becomes the norm. Over time, structure starts drifting, responsibilities blur, and the codebase becomes harder to reason about.</p><p>This piece looks at how to prevent that.</p><p>We&#8217;ll look at practical ways to keep architectural control while still using AI heavily: how to set guardrails before generating code, where AI logic should live once it becomes part of your product, and what to review so &#8220;correct&#8221; output doesn&#8217;t slowly weaken your design.</p><p>AI should accelerate implementation, not quietly define structure or responsibility.</p><h3><strong>When Implementation Speed Becomes the Default</strong></h3><p>When AI integrates into the development environment, the nature of coding changes.</p><p>Developers move from writing every line manually to reviewing and selecting generated suggestions. That shift is efficient, but it also changes what drives consistency in a codebase.</p><p>Suggestions are generated from generalized patterns. They can be correct, but correctness is not the same as architectural alignment.</p><p>A project&#8217;s structure depends on decisions that hold across features, not on what looks plausible inside a single file.</p><h3><strong>Encode Guardrails Before You Generate</strong></h3><p>One practical way to preserve architectural control is to define expectations before generation.</p><p>In practice, this means writing down the constraints that matter in your codebase so the assistant consistently reinforces them.</p><p>For example, a strong instruction set begins by defining the development role clearly:</p><blockquote><p><em>You are an expert in TypeScript, Angular, and scalable web application development. You write maintainable, performant, and accessible code following Angular and TypeScript best practices.</em></p></blockquote><p>From there, it becomes easier to add concrete constraints that prevent structural drift. Even a small rule can make a difference, such as discouraging weak typing:</p><blockquote><p><em>Avoid the any type; use unknown when type is uncertain</em></p></blockquote><p>This kind of guidance does not guarantee perfect output.</p><p>It does something more important: it keeps the assistant working within a defined standard instead of inventing one through suggestion.</p><h3><strong>When AI Becomes Part of the Application</strong></h3><p>The architectural stakes rise when AI is not only assisting development but also powering feature behavior.</p><p>At that point, the questions are no longer about scaffolding. They become questions of placement, responsibility, and cohesion.</p><p>One useful pattern is to configure AI behavior deliberately through a system instruction and then route all interaction through a structured interface.</p><p>Example model configuration and system instruction:</p><p><code>const instructions = `</code></p><p><code>Welcome to citypass.</code></p><p><code>You are a superstar agent for this car parking validator.</code></p><p><code>You will assist users by submitting parking tickets.</code></p><p><code>You can convert date phrases to ISO strings and</code></p><p><code>act as a geocode service to convert a location or address</code></p><p><code>to coordinates long/lat.</code></p><p><code>`;</code></p><p><code>const ai = getAI(firebaseApp);</code></p><p><code>const model = getGenerativeModel(ai, {</code></p><p><code>model: &#8216;gemini-2.5-flash&#8217;,</code></p><p><code>systemInstruction: instructions,</code></p><p><code>tools: [toolset]</code></p><p><code>});</code></p><p><code>this.chat = model.startChat();</code></p><p>This approach makes two architectural decisions explicit.</p><p>First, AI behavior is constrained by a clear instruction. Second, interaction happens through a controlled interface instead of being scattered across unrelated parts of the application.</p><h3><strong>A Practical Boundary: UI for Input, Services for Processing</strong></h3><p>When AI is exposed to users, architectural control often comes down to a simple boundary.</p><p>The UI collects input and shows results. The AI processing stays encapsulated behind an interface that can be tested and evolved.</p><p>A clean example is offering an &#8220;AI Creator&#8221; entry point near an existing workflow, opening a modal to capture a prompt:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rv3r!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38637845-ff08-4516-94e8-0075eef16c05_361x177.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rv3r!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38637845-ff08-4516-94e8-0075eef16c05_361x177.png 424w, https://substackcdn.com/image/fetch/$s_!rv3r!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38637845-ff08-4516-94e8-0075eef16c05_361x177.png 848w, https://substackcdn.com/image/fetch/$s_!rv3r!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38637845-ff08-4516-94e8-0075eef16c05_361x177.png 1272w, https://substackcdn.com/image/fetch/$s_!rv3r!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38637845-ff08-4516-94e8-0075eef16c05_361x177.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rv3r!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38637845-ff08-4516-94e8-0075eef16c05_361x177.png" width="361" height="177" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/38637845-ff08-4516-94e8-0075eef16c05_361x177.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:177,&quot;width&quot;:361,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!rv3r!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38637845-ff08-4516-94e8-0075eef16c05_361x177.png 424w, https://substackcdn.com/image/fetch/$s_!rv3r!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38637845-ff08-4516-94e8-0075eef16c05_361x177.png 848w, https://substackcdn.com/image/fetch/$s_!rv3r!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38637845-ff08-4516-94e8-0075eef16c05_361x177.png 1272w, https://substackcdn.com/image/fetch/$s_!rv3r!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38637845-ff08-4516-94e8-0075eef16c05_361x177.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p><em><strong>Ticket creation flow with an AI Creator entry point used to capture user input for AI-assisted ticket creation.</strong></em></p><p>AI Creator button and modal markup:</p><p><code>&lt;button</code></p><p><code>nz-button</code></p><p><code>nzType=&#8221;link&#8221;</code></p><p><code>type=&#8221;button&#8221;</code></p><p><code>(click)=&#8221;isVisible.set(true)&#8221;</code></p><p><code>&gt;AI Creator</code></p><p><code>&lt;/button&gt;</code></p><p><code>&lt;nz-modal</code></p><p><code>[(nzVisible)]=&#8221;isVisible&#8221;</code></p><p><code>nzTitle=&#8221;AI Creator&#8221;</code></p><p><code>(nzOnCancel)=&#8221;isVisible.set(false)&#8221;</code></p><p><code>(nzOnOk)=&#8221;ok()&#8221;&gt;</code></p><p><code>&lt;ng-container *nzModalContent&gt;</code></p><p><code>&lt;textarea</code></p><p><code>[(ngModel)]=&#8221;prompt&#8221;</code></p><p><code>rows=&#8221;3&#8221;</code></p><p><code>placeholder=&#8221;Enter ticket details&#8221;</code></p><p><code>nz-input&gt;</code></p><p><code>&lt;/textarea&gt;</code></p><p><code>&lt;/ng-container&gt;</code></p><p><code>&lt;/nz-modal&gt;</code></p><p>This interface design matters because responsibility stays clear.</p><p>The component manages interaction and user input. The AI-driven work happens only when the user explicitly triggers it, and the application can decide where that processing belongs.</p><h3><strong>The Drift Risk: Structure by Convenience</strong></h3><p>AI rarely causes dramatic architectural failures.</p><p>The more common risk is incremental drift. A generated approach is accepted, then repeated, and then becomes the default. Over time, similar features are built with slightly different patterns, responsibilities move across layers, and ownership becomes less obvious.</p><p>This is why the guiding principle needs to be visible early in the workflow:</p><p><em><strong>AI should accelerate implementation, not make architectural decisions.</strong></em></p><h3><strong>Maintaining Architectural Control</strong></h3><p>Architectural control in an AI-assisted workflow comes from a small set of repeatable practices:</p><ul><li><p>Define expectations before generation so the assistant reinforces standards</p></li><li><p>Encapsulate AI-enabled behavior behind clear interfaces</p></li><li><p>Review generated code for placement and responsibility, not only for correctness</p></li></ul><p>These practices keep speed from rewriting structure.</p><h3><strong>Final words</strong></h3><p>AI can absolutely increase velocity. It can also unlock product capabilities that would have been expensive or slow to build even a year ago.</p><p>But long-term maintainability still comes down to structure. The difference is that AI changes how structure gets created. It can reinforce good decisions, or it can quietly introduce new patterns through convenience, repetition, and speed.</p><p>That&#8217;s why boundaries matter. When they&#8217;re clear, AI becomes a multiplier for discipline. When they&#8217;re loose, drift becomes the default.</p><p>AI should accelerate implementation, not quietly define structure or responsibility. Architectural control isn&#8217;t about resisting AI. It&#8217;s about staying deliberate while moving fast.</p><p>Want to learn more? Get your copy of <em><strong><a href="https://www.amazon.com/Angular-Projects-building-real-world-enterprise-ebook/dp/B0GDRPDM1P">Angular Projects, 4th Edition</a></strong></em> now!</p><h1><strong>This Week in the News</strong></h1><ul><li><p><strong>&#129513;<a href="https://devblogs.microsoft.com/typescript/announcing-typescript-6-0-beta/">TypeScript 6.0 beta and roadmap shift</a></strong>: <strong>TypeScript 6.0</strong> beta introduces incremental improvements across type checking and configuration while laying groundwork for the long-discussed native rewrite in Go that promises serious performance gains. The team is clearly thinking beyond syntax tweaks and focusing on compiler architecture, which signals that large codebases and build speed are now central to the TypeScript story. For teams pushing monorepos or heavy CI pipelines, this roadmap matters more than any single feature flag.</p></li><li><p><strong>&#128202; <a href="https://2025.stateofjs.com/en-US/">State of JavaScript 2025 survey results</a></strong>: The <em>State of JavaScript 2025</em> survey provides a broad snapshot of how developers are working across the JS ecosystem. <strong>TypeScript continues to see strong adoption</strong>, reinforcing its position as a standard part of modern JavaScript development. In tooling, newer build systems and faster runtimes are gaining momentum, reflecting a clear preference for performance-focused developer experience. The survey also compares usage, satisfaction, and interest across frameworks, testing tools, browser APIs, and runtimes, highlighting which technologies feel stable and which are generating curiosity. Overall, the results show an ecosystem that is maturing around modern defaults while steadily evolving toward faster tooling and more streamlined workflows.</p></li><li><p>&#9883;&#65039; <strong><a href="https://2025.stateofreact.com/en-US?utm_source=chatgpt.com">State of React 2025</a></strong>: The <em>State of React 2025</em> survey offers a data-backed look at how developers are building with React today. Core tooling remains strong: <strong>Next.js, React Router, and Redux</strong> continue to see widespread usage, while <strong>TanStack Query</strong> and <strong>Axios</strong> are common choices for data handling. On the build side, <strong>Vite has emerged as the dominant tool</strong>, reflecting the ecosystem&#8217;s shift toward faster development workflows. UI libraries like <strong>MUI and shadcn/ui</strong> show meaningful adoption, and modern state solutions such as <strong>Redux Toolkit</strong> are preferred when external state is needed. The results also highlight a practical trend: many teams still rely primarily on built-in React APIs for state management, reaching for external libraries only as complexity grows.</p></li></ul><h1><strong>Beyond the Headlines</strong></h1><ul><li><p><strong>&#9889;<a href="https://techhub.iodigital.com/articles/nextjs-at-enterprise-level">Running Next.js at Enterprise Scale</a></strong>: Next.js scales well, but enterprise usage needs more than default settings. This piece breaks down what changes when you&#8217;re running Next.js under real traffic: defining clear SLOs/SLAs, instrumenting performance monitoring, and understanding the framework&#8217;s request lifecycle so you can spot bottlenecks early. It also highlights practical architecture choices like using CDNs and caching effectively, picking the right rendering strategy (SSG vs SSR) per route, and planning for horizontal scaling with shared caches and load balancing.</p></li><li><p><strong>&#128034; <a href="https://symmetrybreak.ing/blog/claude-code-is-being-dumbed-down/">Is Claude Code losing its engineering edge</a></strong>: This post critiques recent shifts in Claude Code&#8217;s behavior, arguing that guardrails and simplifications are reducing its usefulness for experienced developers who value precision and depth. It reflects a broader tension in AI tooling between safety, accessibility, and raw capability. For developers relying on AI as a serious engineering assistant, subtle model behavior changes can have an outsized impact on trust and workflow.</p></li><li><p><strong>&#129517; <a href="https://www.developerway.com/posts/debugging-with-ai">Debugging workflows that actually benefit from AI</a></strong>: An exploration of AI-assisted debugging workflows that break down how you can leverage models to trace issues, interpret stack traces, and accelerate root-cause analysis without feeling like you&#8217;re guessing at prompts.</p></li><li><p><strong>&#9883;&#65039; <a href="https://www.developerway.com/posts/react-server-components-performance">React Server Components performance insights</a></strong>: This piece examines how React Server Components behave in real world performance scenarios, moving past high level explanations to measure tradeoffs in rendering, hydration, and network boundaries. It challenges simplistic assumptions about automatic speed gains and highlights where architectural decisions still matter. For teams evaluating RSC adoption, the nuance here is critical before refactoring large parts of an app around the paradigm.</p></li></ul><h1><strong>Tool of the Week</strong></h1><p>&#127744;&#128736;&#65039; <strong>OpenClaw &#8212; The AI Agent That Does Work for You</strong></p><p>OpenClaw is an <strong>open-source autonomous AI agent</strong> that goes beyond chat: it can execute real tasks like managing email, calendars, messaging apps, and other workflows by integrating with platforms such as WhatsApp, Telegram, and Slack. Developed by Austrian engineer Peter Steinberger, it grew from an experimental project into one of the fastest-adopted agent tools in the community because of its ability to <em>act</em> instead of just <em>respond</em>.</p><p>Since its introduction in November, OpenClaw has seen a viral rise, surpassing <strong>100,000 stars on GitHub</strong> and attracting <strong>2 million visitors in a single week</strong>, signaling strong developer curiosity around agent-based systems.</p><p>This week, OpenClaw made headlines when <strong><a href="https://techcrunch.com/2026/02/15/openclaw-creator-peter-steinberger-joins-openai/">creator Peter Steinberger announced he&#8217;s joining OpenAI</a></strong>. Sam Altman highlighted Steinberger&#8217;s expertise in multi-agent systems as strategically important for building the next generation of personal AI assistants, and OpenClaw will continue as an open-source foundation supported by OpenAI. This move signals how quickly agent-centric tooling is becoming a central focus for major AI platforms.</p><p>For anyone interested in trying OpenClaw yourself or seeing it in action, this tutorial walks through setup and use:&#128250;<a href="https://www.youtube.com/watch?v=n1sfrc-RjyM"> </a><strong><a href="https://www.youtube.com/watch?v=n1sfrc-RjyM">OpenClaw Full Tutorial for Beginners</a></strong>.</p><div><hr></div><p><em>That&#8217;s all for this week. Have any ideas you want to see in the next article? Hit Reply!</em></p><p>Cheers!</p><p>Editor-in-chief,</p><p>Kinnari Chohan</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://packtwebdevpro.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Web Development Newsletter by Packt! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[WebDevPro #125: Where AI actually saves time in modern development workflows]]></title><description><![CDATA[Crafting the Web: Tips, Tools, and Trends for Developers]]></description><link>https://packtwebdevpro.substack.com/p/webdevpro-125-where-ai-actually-saves</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/webdevpro-125-where-ai-actually-saves</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Mon, 09 Feb 2026 14:03:26 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!-Epb!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c609e43-4006-496a-9adf-84620ff6b584_500x500.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to this week&#8217;s issue of WebDevPro!</p><p>Aditya Agarwal, Facebook&#8217;s 10th employee and former CTO of Dropbox, sparked a wider conversation in the developer community this week after sharing a <a href="https://x.com/adityaag/status/2018496292608155756">personal reflection</a> about coding with Claude, Anthropic&#8217;s AI assistant.</p><p>After a weekend building with Claude, he wrote: <em>&#8220;It was very clear that we will never ever write code by hand again.&#8221;</em></p><p>Then he admitted something more surprising: He felt happy, but also disoriented.</p><p>Now that isn&#8217;t a prediction for &#8220;someday.&#8221; It&#8217;s a workflow shift happening right now.</p><p>The real challenge for most teams isn&#8217;t access to AI. It&#8217;s integration. How do you apply AI to scaffolding, debugging, refactoring, UI generation, and delivery pipelines without disrupting your stack or compromising quality?</p><p>That&#8217;s why this upcoming <strong><a href="https://www.telerik.com/webinars/devcraft/ai-for-developers-how-to-achieve-a-50-percent-productivity-boost?utm_medium=cpm&amp;utm_source=webdevpro-emailblast&amp;utm_campaign=dt_ai_productivity_webinar_bitovi">Progress</a></strong><a href="https://www.telerik.com/webinars/devcraft/ai-for-developers-how-to-achieve-a-50-percent-productivity-boost?utm_medium=cpm&amp;utm_source=webdevpro-emailblast&amp;utm_campaign=dt_ai_productivity_webinar_bitovi"> </a>workshop stood out to us. It&#8217;s designed to help developers integrate AI into real workflows, without losing control over quality, security, or governance.</p><div><hr></div><h1><strong><a href="https://www.telerik.com/webinars/devcraft/ai-for-developers-how-to-achieve-a-50-percent-productivity-boost?utm_medium=cpm&amp;utm_source=webdevpro-emailblast&amp;utm_campaign=dt_ai_productivity_webinar_bitovi">Webinar: AI for Developers &#8211; How to Achieve a 50% Productivity Boost</a></strong></h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uWcq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda16d1a3-a353-46ba-b504-693b24ecb1ae_858x267.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uWcq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda16d1a3-a353-46ba-b504-693b24ecb1ae_858x267.png 424w, https://substackcdn.com/image/fetch/$s_!uWcq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda16d1a3-a353-46ba-b504-693b24ecb1ae_858x267.png 848w, https://substackcdn.com/image/fetch/$s_!uWcq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda16d1a3-a353-46ba-b504-693b24ecb1ae_858x267.png 1272w, https://substackcdn.com/image/fetch/$s_!uWcq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda16d1a3-a353-46ba-b504-693b24ecb1ae_858x267.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uWcq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda16d1a3-a353-46ba-b504-693b24ecb1ae_858x267.png" width="858" height="267" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/da16d1a3-a353-46ba-b504-693b24ecb1ae_858x267.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:267,&quot;width&quot;:858,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!uWcq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda16d1a3-a353-46ba-b504-693b24ecb1ae_858x267.png 424w, https://substackcdn.com/image/fetch/$s_!uWcq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda16d1a3-a353-46ba-b504-693b24ecb1ae_858x267.png 848w, https://substackcdn.com/image/fetch/$s_!uWcq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda16d1a3-a353-46ba-b504-693b24ecb1ae_858x267.png 1272w, https://substackcdn.com/image/fetch/$s_!uWcq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda16d1a3-a353-46ba-b504-693b24ecb1ae_858x267.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 class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.telerik.com/webinars/devcraft/ai-for-developers-how-to-achieve-a-50-percent-productivity-boost?utm_medium=cpm&amp;utm_source=webdevpro-emailblast&amp;utm_campaign=dt_ai_productivity_webinar_bitovi&quot;,&quot;text&quot;:&quot;If interested, sign up here&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.telerik.com/webinars/devcraft/ai-for-developers-how-to-achieve-a-50-percent-productivity-boost?utm_medium=cpm&amp;utm_source=webdevpro-emailblast&amp;utm_campaign=dt_ai_productivity_webinar_bitovi"><span>If interested, sign up here</span></a></p><div><hr></div><p>This session breaks down <strong>technical workflows, architectural considerations, and hands-on demos</strong> showing how AI can augment development tasks, without requiring framework changes or replatforming.</p><h1><strong>We&#8217;ll cover topics you care about:</strong></h1><ul><li><p><strong>AI&#8209;Assisted Component Scaffolding</strong><br>How AI can generate baseline UI components, form logic, data-binding structures, and reduce initial setup time.</p></li><li><p><strong>Debugging &amp; Refactoring Using AI Agents</strong><br>Techniques for leveraging AI to identify bottlenecks, suggest optimized patterns, and modernize legacy code.</p></li><li><p><strong>AI&#8209;Enhanced UI Development with Kendo UI &amp; Telerik</strong><br>Practical examples of generating boilerplate, bindings, CRUD screens, tests, and documentation directly from your existing tech stack.</p></li><li><p><strong>Integrating AI into Dev Workflows</strong><br>Where AI fits into CI/CD, code reviews, architectural planning, prototyping, and cross-team collaboration.</p></li><li><p><strong>How Teams Achieve Measurable Gains (up to 50%)</strong><br>Real scenarios showing reduced time spent on repetitive implementation tasks, improved code consistency, and faster iteration cycles.</p></li><li><p><strong>Security &amp; Practical Limitations</strong><br>What to automate, what not to automate, and how to ensure AI&#8209;generated code aligns with team standards.</p></li></ul><h1><strong>Who should attend:</strong></h1><ul><li><p>Senior devs building complex front&#8209;end or full&#8209;stack applications</p></li><li><p>Dev leads and architects driving technical decision&#8209;making</p></li><li><p>Teams exploring AI adoption without changing their existing stack</p></li></ul><p><strong><a href="https://www.telerik.com/webinars/devcraft/ai-for-developers-how-to-achieve-a-50-percent-productivity-boost?utm_medium=cpm&amp;utm_source=webdevpro-emailblast&amp;utm_campaign=dt_ai_productivity_webinar_bitovi">Register &amp; Save Your Seat!</a></strong></p><p>&#128073; <strong>Join the webinar and see how AI can be embedded into real engineering workflows.</strong></p><p><strong>&#128197; February 26, 2026</strong><br><strong>&#9200; 9:30 PM GMT+5:30</strong></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.telerik.com/webinars/devcraft/ai-for-developers-how-to-achieve-a-50-percent-productivity-boost?utm_medium=cpm&amp;utm_source=webdevpro-emailblast&amp;utm_campaign=dt_ai_productivity_webinar_bitovi&quot;,&quot;text&quot;:&quot;Secure your spot!&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.telerik.com/webinars/devcraft/ai-for-developers-how-to-achieve-a-50-percent-productivity-boost?utm_medium=cpm&amp;utm_source=webdevpro-emailblast&amp;utm_campaign=dt_ai_productivity_webinar_bitovi"><span>Secure your spot!</span></a></p>]]></content:encoded></item><item><title><![CDATA[WebDevPro #124 Why Modern JavaScript Feels Fragmented, Plus This Week’s Updates]]></title><description><![CDATA[Crafting the Web: Tips, Tools, and Trends for Developers]]></description><link>https://packtwebdevpro.substack.com/p/webdevpro-124-why-modern-javascript</link><guid isPermaLink="false">https://packtwebdevpro.substack.com/p/webdevpro-124-why-modern-javascript</guid><dc:creator><![CDATA[Kinnari Chohan]]></dc:creator><pubDate>Mon, 02 Feb 2026 14:04:01 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!-Epb!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c609e43-4006-496a-9adf-84620ff6b584_500x500.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://www.telerik.com/webinars/devcraft/ai-for-developers-how-to-achieve-a-50-percent-productivity-boost?utm_medium=cpm&amp;utm_source=webdevpro&amp;utm_campaign=dt_ai_productivity_webinar_bitovi" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QBJT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd71c88ec-0901-495b-b1ff-a7fdd489d735_711x181.png 424w, https://substackcdn.com/image/fetch/$s_!QBJT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd71c88ec-0901-495b-b1ff-a7fdd489d735_711x181.png 848w, https://substackcdn.com/image/fetch/$s_!QBJT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd71c88ec-0901-495b-b1ff-a7fdd489d735_711x181.png 1272w, https://substackcdn.com/image/fetch/$s_!QBJT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd71c88ec-0901-495b-b1ff-a7fdd489d735_711x181.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QBJT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd71c88ec-0901-495b-b1ff-a7fdd489d735_711x181.png" width="728" height="185.32770745428974" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d71c88ec-0901-495b-b1ff-a7fdd489d735_711x181.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:181,&quot;width&quot;:711,&quot;resizeWidth&quot;:728,&quot;bytes&quot;:44290,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:&quot;https://www.telerik.com/webinars/devcraft/ai-for-developers-how-to-achieve-a-50-percent-productivity-boost?utm_medium=cpm&amp;utm_source=webdevpro&amp;utm_campaign=dt_ai_productivity_webinar_bitovi&quot;,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://packtwebdevpro.substack.com/i/186603452?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd71c88ec-0901-495b-b1ff-a7fdd489d735_711x181.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_!QBJT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd71c88ec-0901-495b-b1ff-a7fdd489d735_711x181.png 424w, https://substackcdn.com/image/fetch/$s_!QBJT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd71c88ec-0901-495b-b1ff-a7fdd489d735_711x181.png 848w, https://substackcdn.com/image/fetch/$s_!QBJT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd71c88ec-0901-495b-b1ff-a7fdd489d735_711x181.png 1272w, https://substackcdn.com/image/fetch/$s_!QBJT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd71c88ec-0901-495b-b1ff-a7fdd489d735_711x181.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.telerik.com/webinars/devcraft/ai-for-developers-how-to-achieve-a-50-percent-productivity-boost?utm_medium=cpm&amp;utm_source=webdevpro&amp;utm_campaign=dt_ai_productivity_webinar_bitovi&quot;,&quot;text&quot;:&quot;Save your seat!&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.telerik.com/webinars/devcraft/ai-for-developers-how-to-achieve-a-50-percent-productivity-boost?utm_medium=cpm&amp;utm_source=webdevpro&amp;utm_campaign=dt_ai_productivity_webinar_bitovi"><span>Save your seat!</span></a></p><p>Welcome to this week&#8217;s issue of WebDevPro!</p><p>Before we get into the updates and tools, let&#8217;s start with a familiar moment.</p><p>Imagine this. You&#8217;re deep in a JavaScript codebase, following a clean <code>map</code> and <code>filter</code> chain, when you suddenly land in a class full of mutable state and lifecycle methods. Same language, different mental model. That shift is easy to miss, but over time, it adds real cognitive overhead.</p><p>Modern JavaScript often feels more complicated than it needs to be, even when the syntax itself is familiar. JavaScript doesn&#8217;t neatly transition from one programming style to another as projects grow. Instead, it accumulates them. You might begin with step-by-step procedural code, adopt functional patterns along the way, and later introduce object-based structures to manage scale. In practice, most real-world codebases blend all three.<br><br>In this issue, we&#8217;ll start with a deep dive into JavaScript, looking at how that layering came to be, why it can make code harder to reason about, and how to approach those tradeoffs with more intention. Then we will move on to the key updates from the past week, and wrap up with a tool worth adding to your workflow.</p><h1><strong>Procedural thinking as the foundation</strong></h1><p>For many developers, procedural logic is the starting point. Programs are expressed as a sequence of steps executed in a clear and predictable order. Control flow is explicit, and it is easy to follow how data moves through the program.</p><p>Loops and conditional statements play a central role in this style. They make execution order visible and help explain how decisions affect program behavior.</p><p><code>for (let i = 0; i &lt; items.length; i++) {<br>if (items[i].active) {<br>handle(items[i])<br>}<br>}</code></p><p>This approach emphasizes execution order and state changes. It works well when programs are small and logic is linear. Importantly, this style never disappears. Even as programs grow, procedural code remains a valid and familiar tool.</p><h1><strong>Introducing functional patterns</strong></h1><p>As programs become more complex, functional patterns begin to appear more frequently. Array methods and callbacks provide a more concise way to work with collections and reduce repetitive looping logic.</p><p>Instead of describing how a loop executes, this style focuses on what transformation is applied to the data.</p><p><code>items<br>.filter(item =&gt; item.active)<br>.forEach(handle)</code></p><p>Here, intent is clearer, but control flow is less explicit. Readers must understand how each method behaves and how functions are applied. For some, this improves readability. For others, it introduces a new layer of abstraction that requires adjustment.</p><p>Crucially, this style does not replace procedural logic. Both approaches coexist, and developers are expected to move between them as needed.</p><h1><strong>Shifting toward composition</strong></h1><p>As functional ideas are reinforced, composition becomes more prominent. Functions are treated as reusable building blocks that can be passed around and combined.</p><p>This encourages thinking in terms of data flow rather than execution steps. Logic is expressed by chaining operations together, which can make intent clearer while obscuring the underlying sequence of events.</p><p>At this stage, developers are often working with at least two distinct paradigms simultaneously: procedural control flow and functional composition.</p><h1><strong>Object-based organization for larger programs</strong></h1><p>As programs grow further, object-based organization emerges as a way to manage complexity. Classes and objects group related data and behavior, providing a structural model for larger systems.</p><p><code>class ItemHandler {<br>handle(item) {<br>if (item.active) {<br>// ...<br>}<br>}<br>}</code></p><p>This approach shifts the focus again. Instead of steps or transformations, code is organized around responsibilities and roles.</p><p>Object-based organization can improve clarity in large programs, but it introduces a third way of thinking. Procedural, functional, and object-oriented styles now coexist within the same language and often within the same codebase.</p><h1><strong>Accumulation instead of replacement</strong></h1><p>A defining characteristic of JavaScript is that new paradigms are added without removing older ones. Procedural logic remains valid even as functional patterns appear. Functional composition continues to be useful when object-based structures are introduced.</p><p>Nothing is deprecated at the architectural level. Every style remains available, and developers are free to choose the approach that fits the problem at hand.</p><p>This cumulative nature explains why JavaScript codebases often contain a mixture of paradigms. The language supports each style equally and does not enforce a single architectural direction.</p><h1><strong>Understanding the resulting tension</strong></h1><p>As paradigms accumulate, readers and developers must constantly adjust how they interpret code. Different sections of a program may require different mental models depending on the style being used.</p><p>This flexibility is powerful, but it increases cognitive load. Understanding a program requires not only knowledge of syntax, but also awareness of which paradigm is currently in play.</p><p>Maintaining consistency becomes more challenging as programs grow. The same language constructs can support multiple architectural interpretations depending on context.</p><h1><strong>Final words</strong></h1><p>JavaScript is not broken. It is intentionally flexible.</p><p>The challenge is not choosing the right paradigm, but navigating multiple paradigms at once. When procedural logic, functional composition, and object-based organization coexist, developers must be deliberate about how and when each style is used.</p><p>Understanding how these paradigms accumulate rather than replace one another helps explain why modern JavaScript can feel complex even when the individual concepts are familiar.</p><p>Want to go deeper? <em><strong><a href="https://www.amazon.com/JavaScript-Beginner-Professional-building-interactive/dp/1800562527">JavaScript from Beginner to Professional</a></strong></em><strong> </strong>is a solid pick for developers transitioning into JavaScript. It uses more than 100 practical exercises and projects to develop real, working JavaScript skills.</p><h1><strong>This Week in the News</strong></h1><ul><li><p><strong>&#9881;&#65039; <a href="https://nodejs.org/en/blog/release/v25.5.0">Node.js v25.5.0 Is Out</a></strong>: Node.js has shipped v25.5.0, continuing the steady pace of updates ahead of the next LTS release. This one focuses on runtime fixes and smaller improvements rather than headline features. If you like keeping an eye on where Node is heading next, this release is worth skimming through.</p></li><li><p><strong>&#129521; <a href="https://github.com/sailscastshq/boring-stack">The Boring JavaScript Stack Reaches v1.0</a></strong>: The Boring JavaScript Stack has officially hit v1.0, and the name is very much intentional. It is an opinionated full-stack starter built with Sails, Inertia, Tailwind CSS, plus your choice of Vue, React, or Svelte. The goal here is fewer decisions, less setup churn, and getting to actual product code faster.</p></li><li><p>&#129504;<strong><a href="https://www.youtube.com/watch?v=uMqx8NNT4xY"> A Conversation with Anders Hejlsberg</a></strong>: Last week&#8217;s interview with Anders Hejlsberg offers a thoughtful look into the mindset of one of the most influential language designers behind C# and TypeScript. The discussion touches on language evolution, long-term trade-offs, and what it takes to design tools that scale with both developers and ecosystems. <br>For an overview of the conversation, Aaron Winston summarizes <strong><a href="https://github.blog/developer-skills/programming-languages-and-frameworks/7-learnings-from-anders-hejlsberg-the-architect-behind-c-and-typescript/">Hejlsberg&#8217;s lessons from C# and TypeScript</a></strong> on fast feedback loops, scaling software, open source visibility, and building tools that last.</p></li></ul><h1><strong>Beyond the Headlines</strong></h1><ul><li><p><strong>&#128034; <a href="https://www.viget.com/articles/fixing-typescript-performance-problems">Fixing TypeScript Performance Problems</a></strong>: If your TypeScript project has started to feel slow, this article will feel very familiar. It walks through common causes of sluggish builds and editor lag in larger TS codebases.<br>There are practical fixes here that teams can apply without rewriting everything from scratch.</p></li><li><p><strong>&#129517; <a href="https://dev.to/this-is-learning/javascript-frameworks-heading-into-2026-2hel">JavaScript Frameworks Heading Into 2026</a></strong>: This is a community-driven look at how JavaScript frameworks are shaping up as we move toward 2026. It talks less about hype cycles and more about adoption, trade-offs, and long-term sustainability. A good read if you are thinking about whether to stick, switch, or wait with your current stack.</p></li><li><p><strong>&#127344;&#65039; <a href="https://blog.angular.dev/community-stories-code-samples-and-signal-forms-7d0294475610">Angular Community Stories and Signal Forms</a></strong>: The Angular team shares new community stories along with real-world code samples. There is also an update on Signal Forms, which builds on Angular&#8217;s signals model for handling reactive forms. If you work on form-heavy Angular apps, this is a useful glimpse into where things are going.</p></li><li><p><strong>&#129302; <a href="https://blog.bytebytego.com/p/how-cursor-shipped-its-coding-agent">How Cursor Shipped Its Coding Agent</a></strong>: This post breaks down how Cursor built and shipped its AI coding agent. It goes into architectural decisions, trade-offs, and the realities of putting an AI-assisted dev tool into production. A solid behind-the-scenes read if you are curious about how modern developer tools are actually built.</p></li></ul><h1><strong>Tool of the Week</strong></h1><p>&#9889;<strong><a href="https://bun.com/blog/bun-v1.3.7">Bun Gets Faster with v1.3.7</a></strong></p><p>Bun shipped v1.3.7 last week with a JavaScriptCore update that brings noticeable performance gains, including faster async and await handling and ARM64 improvements. There&#8217;s also a new option to generate profiling data in Markdown for easier sharing, along with native support for JSON5 and JSONL.</p><p>If you are curious why Bun keeps gaining traction, <strong><a href="https://joodi.medium.com/why-developers-are-turning-to-bun-the-new-hotness-in-javascript-2f49eeab340c">this article</a></strong> is still a good explainer on what&#8217;s driving its adoption.</p><p>That&#8217;s all for this week. Have any ideas you want to see in the next article? Hit Comment!</p><p>Cheers!</p><p>Editor-in-chief,</p><p>Kinnari Chohan</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://packtwebdevpro.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Web Development Newsletter by Packt! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item></channel></rss>