<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Devansh</title>
    <description>The latest articles on Forem by Devansh (@devanshhh).</description>
    <link>https://forem.com/devanshhh</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2621947%2F2e4c1e31-b859-4701-8cde-e38cb0175e8e.jpg</url>
      <title>Forem: Devansh</title>
      <link>https://forem.com/devanshhh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/devanshhh"/>
    <language>en</language>
    <item>
      <title>Future of Internet Crawling: WebMCP</title>
      <dc:creator>Devansh</dc:creator>
      <pubDate>Wed, 18 Feb 2026 12:43:22 +0000</pubDate>
      <link>https://forem.com/devanshhh/future-of-internet-crawling-webmcp-m95</link>
      <guid>https://forem.com/devanshhh/future-of-internet-crawling-webmcp-m95</guid>
      <description>&lt;p&gt;For decades, the internet has been crawled the same way humans browse it. Bots download pages, parse HTML, click links, and try to guess what each element does. Search engines do it. Automation tools do it. And now AI agents do it too.&lt;/p&gt;

&lt;p&gt;But there is a problem.&lt;/p&gt;

&lt;p&gt;Modern websites are not simple documents anymore. They are dynamic apps, full of JavaScript, state, authentication, and complex user flows. For AI agents, interacting with them today is like navigating a city by looking at satellite images and guessing where the doors are.&lt;/p&gt;

&lt;p&gt;WebMCP changes that.&lt;/p&gt;

&lt;p&gt;And it may redefine how the internet is crawled and interacted with in the AI era.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with traditional crawling
&lt;/h2&gt;

&lt;p&gt;Let’s understand how AI agents currently work on websites.&lt;/p&gt;

&lt;p&gt;Most agents follow a loop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Load the page&lt;/li&gt;
&lt;li&gt;Take a screenshot or parse the DOM&lt;/li&gt;
&lt;li&gt;Send it to a model&lt;/li&gt;
&lt;li&gt;Decide what to click&lt;/li&gt;
&lt;li&gt;Repeat&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach is:&lt;/p&gt;

&lt;p&gt;Slow, Expensive in tokens, Fragile when UI changes, Often inaccurate&lt;br&gt;
and in many cases, the agent is guessing.&lt;/p&gt;

&lt;p&gt;One report describes this well: today’s agents often rely on screenshots and raw HTML, which forces them to infer where buttons and forms are, consuming large amounts of context just to understand the page.&lt;/p&gt;

&lt;p&gt;This is not scalable for an internet where AI agents may become primary users.&lt;/p&gt;
&lt;h3&gt;
  
  
  Visual understanding: Old Web vs WebMCP
&lt;/h3&gt;

&lt;p&gt;Traditional crawling&lt;/p&gt;

&lt;p&gt;User request: “Book a flight from Mumbai to Delhi”&lt;/p&gt;

&lt;p&gt;Agent workflow:&lt;/p&gt;

&lt;p&gt;Page → Screenshot → Vision model → Find form → Type → Submit → Wait → Parse results&lt;/p&gt;

&lt;p&gt;Each step adds latency and token cost.&lt;/p&gt;
&lt;h2&gt;
  
  
  WebMCP workflow
&lt;/h2&gt;

&lt;p&gt;Website exposes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tool: searchFlights
inputs: origin, destination, date
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;searchFlights({
  origin: "BOM",
  destination: "DEL",
  date: "2026-03-01"
})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No UI interaction. No guessing. No screenshots.&lt;/p&gt;

&lt;p&gt;This structured approach improves efficiency dramatically. Some implementations report up to 89% token savings compared to screenshot-based methods.&lt;/p&gt;

&lt;h3&gt;
  
  
  WebMCP shifts the web from:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Document web → Action web&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crawlers indexed content&lt;/li&gt;
&lt;li&gt;Automation simulated humans&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Websites expose capabilities&lt;/li&gt;
&lt;li&gt;Agents perform tasks directly&lt;/li&gt;
&lt;li&gt;Think of it like the difference between:&lt;/li&gt;
&lt;li&gt;Reading a restaurant menu (HTML)&lt;/li&gt;
&lt;li&gt;Calling orderFood() (WebMCP)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real-world impact scenarios
&lt;/h2&gt;

&lt;p&gt;E-commerce Agent Prompt: “Buy the cheapest noise-cancelling headphones”&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigating pages&lt;/li&gt;
&lt;li&gt;Sorting filters&lt;/li&gt;
&lt;li&gt;Clicking add to cart&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The site exposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;searchProducts()&lt;/li&gt;
&lt;li&gt;addToCart()&lt;/li&gt;
&lt;li&gt;checkout()&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The purchase becomes an API call.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means for the future of crawling
&lt;/h2&gt;

&lt;p&gt;Instead of crawling full pages, sites provide structured context and resources. This reduces processing by more than 60 percent in some evaluations while maintaining high task success rates.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Less scraping, more structured access&lt;/li&gt;
&lt;li&gt;Ranking may change&lt;/li&gt;
&lt;li&gt;Invisible websites risk&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If an AI agent can complete a task directly on a competitor’s site via WebMCP, your UI might never be visited.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;The internet was built for humans. Then it was optimized for search engines. Now it is being redesigned for AI agents.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;WebMCP represents a fundamental shift from crawling pages to executing intentions.&lt;/p&gt;

&lt;p&gt;If this standard succeeds, the future crawler will not scrape your HTML. It will ask your website what it can do.&lt;/p&gt;

&lt;p&gt;And the websites that answer clearly will become the new gateways of the AI web.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>webmcp</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Starvation in Javascript: When your program remains Hungry</title>
      <dc:creator>Devansh</dc:creator>
      <pubDate>Mon, 05 May 2025 18:55:31 +0000</pubDate>
      <link>https://forem.com/devanshhh/starvation-in-javascript-when-your-program-remains-hungry-1i19</link>
      <guid>https://forem.com/devanshhh/starvation-in-javascript-when-your-program-remains-hungry-1i19</guid>
      <description>&lt;p&gt;If you've spent time working with JavaScript's asynchronous model, you know that its single-threaded nature is both a blessing and a curse. On one hand, you don't have to worry about complex locking mechanisms. On the other, you might stumble into weird issues where your code just... never runs. One such issue is starvation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Starvation?
&lt;/h2&gt;

&lt;p&gt;In the context of JavaScript, starvation refers to a situation where a task is perpetually delayed because the event loop is constantly busy with other tasks—usually of higher priority or those scheduled more frequently.&lt;/p&gt;

&lt;p&gt;Since JavaScript executes code in a single-threaded environment using an event loop, starvation can occur when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Long-running synchronous code blocks the event loop.&lt;/li&gt;
&lt;li&gt;Microtasks (Promises, MutationObservers, etc.) continuously prevent macrotasks (like setTimeout, setInterval) from executing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eg : Macrotask Starvation&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function scheduleMacrotask() {
  setTimeout(() =&amp;gt; {
    console.log('Macrotask executed');
  }, 0);
}

function floodMicrotasks() {
  for (let i = 0; i &amp;lt; 1e5; i++) {
    Promise.resolve().then(() =&amp;gt; {
      // Simulate quick microtasks
    });
  }
}

scheduleMacrotask();
floodMicrotasks();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might expect to see "Macrotask executed" logged right away. But the setTimeout callback (a macrotask) gets pushed back behind a flood of microtasks.&lt;/p&gt;

&lt;p&gt;Microtasks in JavaScript are executed immediately after the currently executing script and before any macrotask. So, if you continuously add microtasks, the macrotask keeps getting pushed back. That's starvation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Starvation Happen?
&lt;/h2&gt;

&lt;p&gt;Starvation usually happens due to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Excessive microtask generation&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frequent Promise.resolve().then() in tight loops.&lt;/li&gt;
&lt;li&gt;Recursive promise chains.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Long synchronous blocks&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Functions doing CPU-heavy work without yielding back to the event loop.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Unbalanced priority&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When you schedule many tasks at one level (e.g., microtasks) but never give time for other levels (e.g., macrotasks).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Solution and Workarounds
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Yield with setTimeoutBreak long synchronous code into smaller chunks using setTimeout to allow the event loop to breathe:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function longTask() {
  for (let i = 0; i &amp;lt; 1e6; i++) {
    if (i % 10000 === 0) {
      // Yield to the event loop
      setTimeout(() =&amp;gt; longTask(i + 1), 0);
      return;
    }
    // Do work
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use await with care&lt;br&gt;
If using async/await, be cautious of chaining too many await Promise.resolve() calls without breaks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consider requestIdleCallback (for non-critical work)&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;requestIdleCallback(() =&amp;gt; {
  // Low-priority background task
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Queue microtasks responsibly
Avoid flooding the microtask queue. Instead of a huge batch, spread tasks out:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function chunkMicrotasks(data) {
  function processChunk(index) {
    if (index &amp;gt;= data.length) return;

    // Process a small piece
    for (let i = index; i &amp;lt; index + 100 &amp;amp;&amp;amp; i &amp;lt; data.length; i++) {
      // Do lightweight work
    }

    // Schedule next chunk
    setTimeout(() =&amp;gt; processChunk(index + 100), 0);
  }

  processChunk(0);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Starvation in JavaScript isn't just a theoretical concern—it can cause real performance and responsiveness issues in your applications. &lt;/p&gt;

&lt;p&gt;Understanding how the event loop, microtasks, and macrotasks work together gives you the power to avoid these pitfalls.&lt;/p&gt;

&lt;p&gt;Next time your setTimeout doesn’t seem to fire or your app feels sluggish, take a closer look at your microtask usage and the structure of your event loop.&lt;/p&gt;

&lt;p&gt;Happy 😋 coding!&lt;/p&gt;

&lt;h1&gt;
  
  
  Other resources
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://web.dev/articles/optimize-long-tasks" rel="noopener noreferrer"&gt;https://web.dev/articles/optimize-long-tasks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>eventloop</category>
      <category>deadlock</category>
      <category>webdev</category>
    </item>
    <item>
      <title>We had a socket problem! Working with sockets and APIs</title>
      <dc:creator>Devansh</dc:creator>
      <pubDate>Fri, 27 Dec 2024 14:40:29 +0000</pubDate>
      <link>https://forem.com/devanshhh/we-had-a-socket-problem-working-with-sockets-and-apis-4idp</link>
      <guid>https://forem.com/devanshhh/we-had-a-socket-problem-working-with-sockets-and-apis-4idp</guid>
      <description>&lt;p&gt;Hi, I'm Devansh. A couple of months ago, after integrating sockets on our page that displays order details, our production monitors started going down randomly. They would go down at various times throughout the day without any API failures. We tried reproducing the issue but were unsuccessful. Then, we tracked the production monitor's activities and replicated them exactly in the development environment, where we finally observed the failure.&lt;/p&gt;

&lt;p&gt;On the load of the page, an API call and a socket connection were established on that page to fetch the complete order details. Whenever an event update occurred for that order, only the fields with updated values were sent via the socket response.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Issue
&lt;/h2&gt;

&lt;p&gt;Since the database in production is much larger than the one in the testing environment, API calls sometimes take longer. In such cases, if an update for the order occurs and a socket event is received, the details object would be updated with incomplete but new data. This incomplete data might be missing some necessary keys required by the frontend to load the page, resulting in page errors due to page getting rendered with incomplete data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnrdkwkjxnwhaqbejzc5e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnrdkwkjxnwhaqbejzc5e.png" alt="explaining the issue" width="800" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;We implemented a solution by maintaining a state to temporarily store the socket data. This way, we only update the order details object once the complete response from the API is received. This ensures that the data remains consistent and complete, preventing the frontend from encountering errors due to missing keys&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F774jb1h9m5bqa4mvkaxj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F774jb1h9m5bqa4mvkaxj.png" alt="explaining the solution" width="593" height="716"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>typescript</category>
      <category>nextjs</category>
      <category>react</category>
    </item>
  </channel>
</rss>
