<?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"><channel><title><![CDATA[Manoj's Blog]]></title><description><![CDATA[Manoj's Blog]]></description><link>https://manojuppala.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Mon, 31 Aug 2026 18:35:47 GMT</lastBuildDate><atom:link href="https://manojuppala.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[The Art of Vibe Coding]]></title><description><![CDATA[The Vibe Coder Mindset
AI resembles a junior developer collaborating with you. It's not about asking a single question and moving on; it's about engaging in a dialogue. You provide context, review its]]></description><link>https://manojuppala.hashnode.dev/the-art-of-vibe-coding</link><guid isPermaLink="true">https://manojuppala.hashnode.dev/the-art-of-vibe-coding</guid><category><![CDATA[vibe coding]]></category><category><![CDATA[Artificial Intelligence]]></category><dc:creator><![CDATA[Manoj Uppala]]></dc:creator><pubDate>Wed, 27 May 2026 19:40:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/654670b4cc9a14d65568ae2a/313ba697-972f-4b06-9720-fb12d2b76ba8.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1><strong>The Vibe Coder Mindset</strong></h1>
<p>AI resembles a junior developer collaborating with you. It's not about asking a single question and moving on; it's about engaging in a dialogue. You provide context, review its responses, correct any errors, and steer it toward your requirements. Clearly explaining your ideas enhances its performance.</p>
<p>Unlike traditional programming, where you must know the exact syntax and write everything yourself, AI shifts your role. You become the director rather than the coder. You set the vision, review the output, and ensure the project stays on track. While understanding programming basics is still necessary, you no longer need to memorize syntax or manage every small detail on your own.</p>
<h1><strong>Plan before you Code</strong></h1>
<p>Avoid attempting to build everything at once. Begin with your MVP, the simplest functional version. Avoid trying to build everything simultaneously; proceed step by step. Provide AI with examples such as mockups, screenshots, or code samples to clarify your vision. You can also use AI to assist in planning. Share your idea, let it help refine it, and break it into phases. A bit of planning upfront can save countless hours of revisions later.</p>
<p>For a task manager, this could mean just adding, viewing, and deleting tasks—nothing more. Then, divide the rest into phases: phase two might involve user accounts, and phase three could include notifications. This approach ensures you always have a working product, and AI performs better with smaller, focused tasks rather than tackling an entire app at once.</p>
<h3><strong>Work step by step rather than trying to build all at once</strong></h3>
<p>Develop one feature at a time. Request the AI to implement it, test it, ensure it functions correctly, and then proceed to the next feature. If you ask AI to handle too many tasks simultaneously, issues will arise, and identifying the cause will be challenging. Taking small steps simplifies debugging, as changes are isolated, making it easy to pinpoint problems.</p>
<h3><strong>Illustrate AI with Examples</strong></h3>
<p>Always provide AI with visual references, not just text. Include existing files, screenshots, or reference links. The more relevant material you supply, the less guessing is required, resulting in better output.</p>
<h3><strong>Implement Spec-Driven Development (SDD)</strong></h3>
<p>Spec-driven development involves creating a detailed document outlining what you intend to build before initiating any prompts. Rather than immediately asking AI to generate code, begin by describing the features, user flows, data structure, and key rules. Provide this document to the AI at the start of each session to ensure it has a comprehensive understanding.</p>
<h1><strong>Tech Stack and Coding</strong></h1>
<p>Use well-known tech stacks such as React, Next.js, Tailwind, and Supabase. AI is trained extensively on these tools, leading to improved results. For mobile, desktop, or hardware projects, the same principle applies: rely on established tools. Using niche or very new technologies increases the likelihood of errors and requires more time for corrections. Popular stacks also offer more tutorials and community support, which is beneficial when encountering challenges.</p>
<h3><strong>If you have style/coding preferences, document them for AI</strong></h3>
<p>Document your preferences—such as folder structure, naming conventions, and coding patterns—in a dedicated file (e.g., a CLAUDE.md). Share this with AI at the beginning of each session to avoid repetitive corrections and ensure consistent code throughout the project.</p>
<h3><strong>Ask AI to keep the code modular and aim for smaller modules/files</strong></h3>
<p>Right from the beginning, instruct AI to divide the code into small, focused files instead of consolidating everything in one place. Smaller files are easier to read, fix, and allow AI to work more effectively in future sessions without confusion.</p>
<h3><strong>Regularly ask the AI to review and refactor the codebase</strong></h3>
<p>Every few sessions, take a break from developing new features and ask the AI to tidy up the existing code. As time passes, code can become disorganized, so regular cleanups help maintain the project's integrity and ensure continued development without unexpected issues.</p>
<h3><strong>Use skills created by others</strong></h3>
<p>A growing ecosystem of skills—pre-built AI capabilities developed as an open standard—can be integrated into your AI tool to enhance its functionality. Before creating something new, see if an existing skill can meet your needs. This approach saves time and often yields better results than starting from scratch.</p>
<h1><strong>Security Best Practices</strong></h1>
<p>Before making anything public, ensure the AI reviews the code for security vulnerabilities such as unprotected routes, missing input validation, exposed data, and other potential exploits. Consider this a mandatory step, not optional.</p>
<p>API keys, passwords, and tokens should never appear directly in your code. Store them in a <code>.env</code> file using environment variables, and make sure that file is listed in <code>.gitignore</code> so it never gets pushed to GitHub accidentally.</p>
<h1><strong>Prompting Best Practices</strong></h1>
<h3><strong>Ask for one task at a time</strong></h3>
<p>Keep your prompts focused. Request the AI to perform a single task, review the outcome, and then proceed to the next. Combining multiple requests in one prompt can cause the AI to lose focus, leading to errors across all tasks.</p>
<h3><strong>Be specific about what you want</strong></h3>
<p>Describe exactly what you want — layout, behavior, content, constraints. The more detail you give, the less the AI has to guess. Vague prompts produce vague results, and you end up spending more time correcting than if you had been specific from the start.</p>
<h3><strong>Regularly update your context document</strong></h3>
<p>Whenever you make a significant decision about your project, include it in your context document, such as your CLAUDE.md. This practice shortens sessions, minimizes repeated explanations, and conserves tokens, ultimately saving money, particularly when using agents that quickly consume tokens.</p>
<h3><strong>Explicitly tell AI to "think" or "brainstorm"</strong></h3>
<p>For tricky problems, don't ask AI to jump straight to a solution. Tell it to think through the options first and explain its reasoning before writing any code. This simple instruction often leads to much better results on complex tasks.</p>
<h1><strong>Context</strong></h1>
<p>When working with AI, context is crucial. The AI only understands what you communicate; it lacks memory of your project, past decisions, or preferences unless you provide that information during the current session. Keep sessions focused, begin anew for unrelated tasks, and use subagents when possible to maintain clarity and reduce costs.</p>
<h3><strong>Leverage long context windows</strong></h3>
<p>Certain AI tools enable you to input a large amount of information simultaneously. For complex tasks, provide the AI with all pertinent files, notes, and context at once. The more the AI comprehends your project from the start, the better decisions it will make during the session.</p>
<h3><strong>If AI fails after 3 prompts, stop</strong></h3>
<p>If the AI continues to make errors after three attempts, it's advisable to stop and try a different approach. Begin a new session and rephrase your request entirely. Starting fresh is often more effective than attempting to correct a conversation that has derailed.</p>
<h3><strong>For unrelated tasks, clean and start new sessions</strong></h3>
<p>When transitioning to a different task, initiate a new chat. Continuing context from an unrelated session confuses the AI, diminishes response quality, and wastes tokens on irrelevant information.</p>
<h3><strong>Use subagents</strong></h3>
<p>Subagents are specialized agents designed to manage specific tasks within their own isolated context. Employing them ensures each task remains focused, minimizes token usage, and yields cleaner results compared to handling everything in a single extended conversation.</p>
<h1><strong>Debugging</strong></h1>
<p>AI excels at correcting errors when provided with accurate information. Directly paste the error message for diagnosis, and if it continues to fail after a few tries, request a list of all possible causes instead of guessing. Utilize logs to pinpoint where issues arise, and when possible, use MCP tools to grant AI real-time insight into your app's internal processes.</p>
<h3><strong>Install and ask AI to use MCP</strong></h3>
<p>MCP tools enable AI to interact directly with your app, such as using Playwright to test it in a real browser. This provides AI with actual visibility into the app's operations, enhancing the speed and accuracy of debugging by eliminating reliance on code-based assumptions.</p>
]]></content:encoded></item><item><title><![CDATA[AWS API Gateway Websocket With Lambda]]></title><description><![CDATA[Real-time communication is a core requirement for modern applications like chat apps, live dashboards, multiplayer games, and notifications. AWS makes this easier with API Gateway WebSockets and AWS Lambda, allowing you to build scalable, serverless,...]]></description><link>https://manojuppala.hashnode.dev/aws-api-gateway-websocket-with-lambda</link><guid isPermaLink="true">https://manojuppala.hashnode.dev/aws-api-gateway-websocket-with-lambda</guid><category><![CDATA[AWS]]></category><category><![CDATA[websockets]]></category><category><![CDATA[API Gateway]]></category><category><![CDATA[lambda]]></category><dc:creator><![CDATA[Manoj Uppala]]></dc:creator><pubDate>Sun, 04 Jan 2026 05:44:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1766325093046/98921078-f752-4617-8984-b05bf6be028a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Real-time communication is a core requirement for modern applications like chat apps, live dashboards, multiplayer games, and notifications. AWS makes this easier with <strong>API Gateway WebSockets</strong> and <strong>AWS Lambda</strong>, allowing you to build scalable, serverless, real-time APIs without managing servers.</p>
<p>In this blog, we’ll walk through <strong>how to set up an AWS WebSocket API using API Gateway and Lambda</strong>, including connection handling, messaging, and deployment.</p>
<h2 id="heading-create-a-api-gateway-websocket-based-endpoint">Create a API Gateway Websocket based endpoint</h2>
<p>Open the API Gateway on aws console and create a websocket api.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767028889840/cf56dfcb-552c-4d1e-a6ad-6cbaba4c5ce2.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767028906082/ae7ac6cb-c78c-4a11-adb5-bab5d035a501.png" alt class="image--center mx-auto" /></p>
<p>Then give your api a name and add the route selection expression (i’m going to leave it with the default <code>request.body.action</code>).</p>
<p>The way route selection works is when someone sends a message to your api gateway websocket endpoint, they pass an action along with the message. This action determines what lambda function we invoke in the backend (It’ll make more sense further into the blog).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767030286335/57f6247c-b721-422c-96ac-3416f1e7248a.png" alt class="image--center mx-auto" /></p>
<p>Next, setup the predefined and custom routes. In addition to <code>$connect</code> and <code>$disconnect</code> routes I’m going to define a <code>sendMessage</code> route.</p>
<p>In an API Gateway <strong>WebSocket API</strong>, routes define what code runs when something happens on a WebSocket connection. Unlike REST APIs (which respond to HTTP methods like GET or POST), WebSocket APIs respond to <strong>connection events and messages</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767030828041/350c9868-6b02-4192-b56b-5feffbca5066.png" alt class="image--center mx-auto" /></p>
<p>Now we’re going to add integrations for all of our routes. As the blog title suggests the integration type will be <strong>Lambda</strong>. We’ll see what goes into the lambda functions in detail further into the blog.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767048183818/9d0da741-86e7-41df-b03b-8ba46a28c14d.png" alt class="image--center mx-auto" /></p>
<p>Finally name your stage, create and deploy the websocket.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767048314990/9efa88fc-5d65-4cb5-b7de-77b235184572.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-lets-explore-the-websocket">Let’s Explore the Websocket</h2>
<p>Go to the API Gateway home page and open the Demo api we just created. Here you’ll see all the routes we configured. Make sure to deploy the api if you make any changes to the routes in the future.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767048826922/a16c9517-a786-4b3b-913b-b285305d601e.png" alt class="image--center mx-auto" /></p>
<p>To start messing with the websocket we’ll need the websocket endpoint. Go to stages &gt; production (or whatever the name of your stage is).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767049062628/044ef68b-e440-4410-9ab7-443fb646da10.png" alt class="image--center mx-auto" /></p>
<p>Now, to test the websocket URL you can use any of the online websocket testing tools or postman. I’m using <a target="_blank" href="https://piehost.com/websocket-tester">https://piehost.com/websocket-tester</a>. Paste the websocket URL and connect.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767049357365/fa95d12b-a96b-4d7e-94a2-cfb3c90a7ba9.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767049374058/ec37e8e2-b88f-4e1f-8584-9b2d7f690e8b.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-now-lets-talk-lambdas">Now let’s talk Lambdas</h2>
<p>Now that we are connected to the websocket let’s define our lambdas and how we want them to respond to the sendMessage route and broadcast messages to all active connections. Just go ahead and create 4 basic lambdas. I’m using Node.js, you can use the Runtime of your choice.</p>
<p>We have 4 functions here, we’ve already mapped three(<code>connect</code>, <code>disconnect</code> and <code>sendMessage</code>) of them to the routes while creating the websocket. broadcast is how we’ll communicate with all active connections.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767049895283/06aeea8f-45b0-49fb-8af6-c904fb9a0b79.png" alt class="image--center mx-auto" /></p>
<p>Always remember to return as <code>statusCode</code> 200 from your lambda function. This indicates to the API Gateway that the function executed successfully and the data should be passed back to the connected client as a message.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> handler = <span class="hljs-keyword">async</span> (event) =&gt; {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'event'</span>, event);
  <span class="hljs-comment">// TODO implement</span>
  <span class="hljs-keyword">const</span> response = {
    <span class="hljs-attr">statusCode</span>: <span class="hljs-number">200</span>,
    <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify(<span class="hljs-string">'Hello from Lambda!'</span>),
  };
  <span class="hljs-keyword">return</span> response;
};
</code></pre>
<p>As we are already connected, So let’s go to the monitor tab and check the cloud watch logs for the connect function.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767050477556/b1fc273d-5681-4f3c-aa80-f0fb93e80331.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767050635840/39844980-d098-4c5d-9b4b-faa2b07ecba3.png" alt class="image--center mx-auto" /></p>
<p>And open the latest log stream</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767050652085/aae62a4a-378b-471b-9013-b2b603cf760d.png" alt class="image--center mx-auto" /></p>
<p>What we are looking for here is the event and the requestContext. We are looking for the <code>connectionId</code> in particular:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767050827263/83cc2906-d03a-4147-b1fe-867177fde070.png" alt class="image--center mx-auto" /></p>
<p>The <code>connectionId</code> will be unique for each connection. When you are dealing with applications where there are multiple users connnected at a point, you might want to save these <code>connectionId</code>’s to a database to keep a track of all the connections that are active.</p>
<h2 id="heading-sendmessage-lambda">SendMessage Lambda</h2>
<p>The following is the code for <strong>SendMessage</strong> Lambda. We’ll use the <code>ApiGatewayManagementApiClient</code> to respond to messages. Get the endpoint URL from API Gateway, and <code>PostToConnectionCommand</code> is used to post message back to the connected client. Remember to return a statusCode of 200 at the end of every lambda.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> {
  ApiGatewayManagementApiClient,
  PostToConnectionCommand
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@aws-sdk/client-apigatewaymanagementapi"</span>;

<span class="hljs-keyword">const</span> client = <span class="hljs-keyword">new</span> ApiGatewayManagementApiClient({
  <span class="hljs-attr">endpoint</span>: <span class="hljs-string">"https://xxxxxxxxxx.com/production"</span>
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> handler = <span class="hljs-keyword">async</span> (event) =&gt; {
  <span class="hljs-built_in">console</span>.log(event);

  <span class="hljs-comment">// Extract connectionId from incoming event</span>
  <span class="hljs-keyword">const</span> connectionId = event.requestContext.connectionId;

  <span class="hljs-comment">// Do something interesting...</span>
  <span class="hljs-keyword">const</span> responseMessage = <span class="hljs-string">"responding..."</span>;

  <span class="hljs-comment">// Post message back to the connected client</span>
  <span class="hljs-keyword">const</span> command = <span class="hljs-keyword">new</span> PostToConnectionCommand({
    <span class="hljs-attr">ConnectionId</span>: connectionId,
    <span class="hljs-attr">Data</span>: Buffer.from(<span class="hljs-built_in">JSON</span>.stringify(responseMessage))
  });

  <span class="hljs-keyword">await</span> client.send(command);

  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">statusCode</span>: <span class="hljs-number">200</span>
  };
};
</code></pre>
<p>In addition to this, any lambda function that uses <code>ApiGatewayManagementApiClient</code> to post back to an endpoint needs to have the <code>AmazonAPIGatewayInvokeFullAccess</code> permission policy, Add the <code>AmazonAPIGatewayInvokeFullAccess</code> permission policy to the <code>SendMessage-role</code> under lambda permissions. Don’t forget to redeploy your lambda after adding any new policies to the function’s role.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767239662533/1d7c6d90-bec5-408c-8b6a-f6b3404835b1.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767239696151/737ef9fb-3a3c-4bc7-a9b2-97984dcbf076.png" alt class="image--center mx-auto" /></p>
<p>Now to send the message, remember the <strong>Route selection expression</strong> we used in the start while creating the API gateway endpoint? That is what we’ll use. The request goes something like this:</p>
<pre><code class="lang-javascript">{<span class="hljs-string">"action"</span>: <span class="hljs-string">"sendMessage"</span>, <span class="hljs-string">"message"</span>: <span class="hljs-string">"hello"</span>}
</code></pre>
<p>You’ll see the “responding…“, which means your message has been received.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767239741246/f1140d5d-fa34-4856-94fb-09ed21ff13a0.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-broadcast-lambda">Broadcast Lambda</h2>
<p>This is what we’ll use to push messages to all the available clients that are currently connected. If you look at the code this does something very similar to the <strong>SendMessage</strong> lambda. We’ll pass the <code>connectionId</code> of the user in the event along with the <code>message</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> {
  ApiGatewayManagementApiClient,
  PostToConnectionCommand
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@aws-sdk/client-apigatewaymanagementapi"</span>;

<span class="hljs-keyword">const</span> client = <span class="hljs-keyword">new</span> ApiGatewayManagementApiClient({
  <span class="hljs-attr">endpoint</span>: <span class="hljs-string">"https://xxxxxx.com/production"</span>
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> handler = <span class="hljs-keyword">async</span> (event) =&gt; {
  <span class="hljs-comment">// Extract connectionId and message from input</span>
  <span class="hljs-keyword">const</span> { connectionId, message } = event;

  <span class="hljs-comment">// Send message to the given connectionId</span>
  <span class="hljs-keyword">const</span> command = <span class="hljs-keyword">new</span> PostToConnectionCommand({
    <span class="hljs-attr">ConnectionId</span>: connectionId,
    <span class="hljs-attr">Data</span>: Buffer.from(<span class="hljs-built_in">JSON</span>.stringify(message))
  });

  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> client.send(command);
  <span class="hljs-built_in">console</span>.log(response);
};
</code></pre>
<p>This is how the request looks like, (You can get the <code>connectionId</code> from request in the Cloudwatch logs, when the user <code>connected</code> or during <code>sendMessage</code>):</p>
<pre><code class="lang-javascript">{
  <span class="hljs-string">"connectionId"</span>: <span class="hljs-string">"WfPxee4tvHcCJIw="</span>,
  <span class="hljs-string">"message"</span>: <span class="hljs-string">"Is anyone online?"</span>
}
</code></pre>
<p>Once you deploy the function, Create a new test event. Add the above request to <strong>Event JSON</strong> and <strong>Invoke</strong>. Don’t forget to apply the same permission policy to Broadcast function that we applied to SendMessage (<code>AmazonAPIGatewayInvokeFullAccess</code>).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767505151896/925b004b-3b11-482f-aec9-9960fc4a425e.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767504240158/62e10a68-f60f-4bf9-8151-055381272106.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-the-end">The End</h2>
<p>AWS API Gateway WebSockets combined with Lambda offer a powerful, fully serverless way to build real-time applications. Once you understand how <code>$connect</code>, <code>$disconnect</code>, <code>$default</code>, and custom routes work together, the overall model becomes surprisingly simple and flexible.</p>
<p>In this guide, we covered how to set up a WebSocket API, route messages correctly, and send responses back to connected clients using the API Gateway Management API. From here, you can extend this foundation with authentication, DynamoDB-backed connection management, broadcasting, or more advanced message routing.</p>
<p>If you’re building chat systems, live dashboards, multiplayer features, or real-time notifications, this architecture gives you a scalable solution without the operational overhead of managing servers.</p>
<p>Happy building!</p>
]]></content:encoded></item><item><title><![CDATA[How to Use Chrome Dev Tools for Mocking API Responses Locally]]></title><description><![CDATA[Have you ever wondered if you could mock the API responses while working on a project where the deployment cycle is long, APIs aren't ready, or if you're a QA tester and want to test how the frontend reacts to different API responses? Local overrides...]]></description><link>https://manojuppala.hashnode.dev/how-to-use-chrome-dev-tools-for-mocking-api-responses-locally</link><guid isPermaLink="true">https://manojuppala.hashnode.dev/how-to-use-chrome-dev-tools-for-mocking-api-responses-locally</guid><category><![CDATA[Chrome]]></category><category><![CDATA[Chrome DevTool]]></category><category><![CDATA[APIs]]></category><dc:creator><![CDATA[Manoj Uppala]]></dc:creator><pubDate>Sat, 20 Sep 2025 09:14:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1712873279934/16ab6727-735a-4e50-bbde-49f01036f965.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Have you ever wondered if you could mock the API responses while working on a project where the deployment cycle is long, APIs aren't ready, or if you're a QA tester and want to test how the frontend reacts to different API responses? Local overrides are a Chrome 117 feature that allows you to mock your API responses and here's how they work. Local overrides are helpful when you want to try changes on a website without affecting the live version or when you want to test a bug fix without making permanent changes. They offer an easy way to preview and adjust modifications before applying them to the actual server files.</p>
<p>Keep in mind that local overrides are stored on your computer and do not affect the website or its files on the server. Also, local overrides are only active when DevTools is open, and the changes apply only to the browser profile you are using.</p>
<p>Remember to remove or disable local overrides when you no longer need them, as they can interfere with the website's normal behavior if left active.</p>
<h2 id="heading-setup-overrides">Setup Overrides</h2>
<p>First, you'll have to create a folder to store your override files. To do this go to overrides under the sources tab and add a folder.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758353479821/e401bee9-2532-4c41-9825-804278a13006.png" alt class="image--center mx-auto" /></p>
<p>Once you've selected a folder to store your overrides you'll be prompted to give Chrome full access to the folder.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758357330760/eb48e909-c5e9-4c9a-9c27-dac3e0b496db.png" alt class="image--center mx-auto" /></p>
<p>Now go to the network tab, choose the request you want to mock, right click, and "override content".</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758353557063/787d9ce6-4d2e-4862-9ed9-3004642f8357.png" alt class="image--center mx-auto" /></p>
<p>Then you'll have a local version of the same file you can open this with your favourite editor and start playing.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758356487461/1e9e794f-06bb-4e34-9f95-52ab6be64da9.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-override-response-headers">Override Response Headers</h2>
<p>Using overrides you can mock response headers as well. This is helpful for testing CORS issues or any other header changes.</p>
<p>Select the network call you want to mock and click the edit icon next to the header you want to edit.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758358679718/05bdc753-444d-4640-bd3f-6a9c6505de48.png" alt class="image--center mx-auto" /></p>
<p>once you edit the header a override file for headers will be added and you can edit the existing headers or add new ones.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758358795466/03768677-bc8f-4c4f-a073-18420a44e862.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>“Local overrides” are a useful tool for developers to debug functions that act differently in local environments compared to production or staging. By taking the time to learn and use this feature, developers can save a lot of time when fixing code problems.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Polyfills and Transpilers in JavaScript]]></title><description><![CDATA[Modern JavaScript development comes with unique challenges because the language is evolving quickly with new features and syntax, while still needing to work with older browsers and environments. This blog explores two important tools that help devel...]]></description><link>https://manojuppala.hashnode.dev/understanding-polyfills-and-transpilers-in-javascript</link><guid isPermaLink="true">https://manojuppala.hashnode.dev/understanding-polyfills-and-transpilers-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Browsers]]></category><category><![CDATA[ES6]]></category><category><![CDATA[polyfills]]></category><dc:creator><![CDATA[Manoj Uppala]]></dc:creator><pubDate>Mon, 08 Sep 2025 17:34:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1704630234934/795c0acc-8bfa-406a-85b7-4a562a597900.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Modern JavaScript development comes with unique challenges because the language is evolving quickly with new features and syntax, while still needing to work with older browsers and environments. This blog explores two important tools that help developers connect the latest JavaScript features with real-world browser support: polyfills and transpilers.</p>
<p>The JavaScript ecosystem has grown rapidly, with new ECMAScript features being added every year through ES6, ES7, ES8, and beyond. Recent statistics show that about <strong>83%</strong> of web browsers now support ES6+ features. However, developers still need to consider the <strong>17%</strong> of users who use older environments. This situation requires strategies to use modern JavaScript while ensuring wide compatibility.</p>
<h2 id="heading-polyfills">Polyfills</h2>
<p>A polyfill is a piece of code that adds modern features to older browsers that don't support them natively. The term "polyfill" refers to code that "fills in" the gaps where certain features are missing. Unlike transpilers, which change the syntax, polyfills add missing functionality while the code is running.</p>
<p>Polyfills work by checking if a feature or API is missing in a browser and then providing a custom implementation using existing JavaScript capabilities. This lets developers use the latest JavaScript features and APIs without worrying about browser compatibility problems.</p>
<h3 id="heading-how-polyfills-work">How Polyfills Work</h3>
<p>The fundamental mechanism of polyfills involves feature detection followed by implementation. Here's the typical pattern:</p>
<pre><code class="lang-javascript">javascript<span class="hljs-comment">// Feature detection</span>
<span class="hljs-keyword">if</span> (!<span class="hljs-built_in">Array</span>.prototype.includes) {
  <span class="hljs-comment">// Polyfill implementation</span>
  <span class="hljs-built_in">Array</span>.prototype.includes = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">searchElement</span>) </span>{
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-built_in">this</span>.length; i++) {
      <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>[i] === searchElement) {
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
      }
    }
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  };
}

<span class="hljs-comment">// Now safe to use</span>
<span class="hljs-built_in">console</span>.log([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>].includes(<span class="hljs-number">2</span>)); <span class="hljs-comment">// true</span>
</code></pre>
<p>This example demonstrates polyfilling the <code>Array.prototype.includes()</code> method, which determines whether an array includes a specific element but isn't supported in Internet Explorer 11.</p>
<h3 id="heading-common-polyfill-examples">Common Polyfill Examples</h3>
<h3 id="heading-array-methods">Array Methods</h3>
<p>Modern JavaScript introduced several array methods that require polyfilling for older browsers:</p>
<pre><code class="lang-javascript">javascript<span class="hljs-comment">// Array.prototype.find polyfill</span>
<span class="hljs-keyword">if</span> (!<span class="hljs-built_in">Array</span>.prototype.find) {
  <span class="hljs-built_in">Array</span>.prototype.find = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">predicate</span>) </span>{
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-built_in">this</span>.length; i++) {
      <span class="hljs-keyword">if</span> (predicate(<span class="hljs-built_in">this</span>[i], i, <span class="hljs-built_in">this</span>)) {
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>[i];
      }
    }
    <span class="hljs-keyword">return</span> <span class="hljs-literal">undefined</span>;
  };
}

<span class="hljs-comment">// Array.prototype.filter polyfill</span>
<span class="hljs-keyword">if</span> (!<span class="hljs-built_in">Array</span>.prototype.filter) {
  <span class="hljs-built_in">Array</span>.prototype.filter = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">callback</span>) </span>{
    <span class="hljs-keyword">var</span> filtered = [];
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-built_in">this</span>.length; i++) {
      <span class="hljs-keyword">if</span> (callback(<span class="hljs-built_in">this</span>[i], i, <span class="hljs-built_in">this</span>)) {
        filtered.push(<span class="hljs-built_in">this</span>[i]);
      }
    }
    <span class="hljs-keyword">return</span> filtered;
  };
}
</code></pre>
<h3 id="heading-promise-api">Promise API</h3>
<p>The Promise API, fundamental to modern asynchronous JavaScript, requires comprehensive polyfilling for older environments:</p>
<pre><code class="lang-javascript">javascript<span class="hljs-comment">// Promise.all polyfill</span>
<span class="hljs-keyword">if</span> (!<span class="hljs-built_in">Promise</span>.all) {
  <span class="hljs-built_in">Promise</span>.all = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">promises</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> result = [];
      <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>;

      <span class="hljs-keyword">if</span> (promises.length === <span class="hljs-number">0</span>) {
        resolve(result);
        <span class="hljs-keyword">return</span>;
      }

      <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; promises.length; i++) {
        <span class="hljs-built_in">Promise</span>.resolve(promises[i]).then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> {
          result[i] = res;
          count++;
          <span class="hljs-keyword">if</span> (count === promises.length) {
            resolve(result);
          }
        }, reject);
      }
    });
  };
}
</code></pre>
<h3 id="heading-fetch-api">Fetch API</h3>
<p>The Fetch API provides a modern alternative to XMLHttpRequest but requires polyfilling for older browsers:</p>
<pre><code class="lang-javascript">javascript<span class="hljs-comment">// Basic fetch polyfill concept</span>
<span class="hljs-keyword">if</span> (!<span class="hljs-built_in">window</span>.fetch) {
  <span class="hljs-built_in">window</span>.fetch = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">url, options</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> xhr = <span class="hljs-keyword">new</span> XMLHttpRequest();
      xhr.open(options?.method || <span class="hljs-string">'GET'</span>, url);

      <span class="hljs-built_in">Object</span>.keys(options?.headers || {}).forEach(<span class="hljs-function"><span class="hljs-params">key</span> =&gt;</span> {
        xhr.setRequestHeader(key, options.headers[key]);
      });

      xhr.onload = <span class="hljs-function">() =&gt;</span> {
        resolve({
          <span class="hljs-attr">ok</span>: xhr.status &gt;= <span class="hljs-number">200</span> &amp;&amp; xhr.status &lt; <span class="hljs-number">300</span>,
          <span class="hljs-attr">status</span>: xhr.status,
          <span class="hljs-attr">json</span>: <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">Promise</span>.resolve(<span class="hljs-built_in">JSON</span>.parse(xhr.responseText)),
          <span class="hljs-attr">text</span>: <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">Promise</span>.resolve(xhr.responseText)
        });
      };

      xhr.onerror = <span class="hljs-function">() =&gt;</span> reject(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Network error'</span>));
      xhr.send(options?.body);
    });
  };
}
</code></pre>
<h3 id="heading-popular-polyfill-libraries">Popular Polyfill Libraries</h3>
<h3 id="heading-core-js">core-js</h3>
<p>Core-js is the most comprehensive polyfill library, offering modular support for ECMAScript features up to 2025. It lets you include only the polyfills you need:</p>
<pre><code class="lang-javascript">javascript<span class="hljs-comment">// Import specific polyfills</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'core-js/actual/array/flat-map'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'core-js/actual/promise'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'core-js/actual/array/includes'</span>;

<span class="hljs-comment">// Or import all stable features</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'core-js/stable'</span>;
</code></pre>
<h2 id="heading-transpilers">Transpilers</h2>
<p>A transpiler (or transcompiler) is a special type of compiler that converts source code written in one programming language into equivalent source code in another language at a similar level of abstraction. In JavaScript contexts, transpilers convert modern JavaScript syntax (ES6+) into older versions (typically ES5) that older browsers can execute.</p>
<h3 id="heading-how-transpilers-work">How Transpilers Work</h3>
<p>Transpilers operate through three main phases:</p>
<ol>
<li><p><strong>Parse</strong>: The transpiler analyzes the source code and generates an Abstract Syntax Tree (AST)</p>
</li>
<li><p><strong>Transform</strong>: The AST is traversed, and nodes are modified, added, or removed as needed</p>
</li>
<li><p><strong>Generate</strong>: The modified AST is converted back into executable code</p>
</li>
</ol>
<p>Here's how modern syntax gets transformed:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ES6+ Input</span>
<span class="hljs-keyword">const</span> greet = <span class="hljs-function">(<span class="hljs-params">name</span>) =&gt;</span> <span class="hljs-string">`Hello, <span class="hljs-subst">${name}</span>!`</span>;
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
  <span class="hljs-keyword">constructor</span>(name) {
    <span class="hljs-built_in">this</span>.name = name;
  }
}

<span class="hljs-comment">// ES5 Output</span>
<span class="hljs-keyword">var</span> greet = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">name</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello, "</span> + name + <span class="hljs-string">"!"</span>;
};

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">User</span>(<span class="hljs-params">name</span>) </span>{
  <span class="hljs-built_in">this</span>.name = name;
}
</code></pre>
<h3 id="heading-popular-transpilers">Popular Transpilers</h3>
<h3 id="heading-babel">Babel</h3>
<p>Babel is the most prominent JavaScript transpiler, providing comprehensive ES6+ to ES5 transformation capabilities. Setting up Babel involves several steps:</p>
<pre><code class="lang-javascript">bash# Install Babel core packages
npm install --save-dev @babel/core @babel/cli @babel/preset-env
</code></pre>
<p>Configuration through <code>.babelrc</code>:</p>
<pre><code class="lang-javascript">json{
  <span class="hljs-string">"presets"</span>: [<span class="hljs-string">"@babel/preset-env"</span>]
}
</code></pre>
<p>Advanced configuration with specific browser targets:</p>
<pre><code class="lang-javascript">json{
  <span class="hljs-string">"presets"</span>: [
    [<span class="hljs-string">"@babel/preset-env"</span>, {
      <span class="hljs-string">"targets"</span>: {
        <span class="hljs-string">"browsers"</span>: [<span class="hljs-string">"&gt; 0.25%, not dead"</span>]
      }
    }]
  ]
}
</code></pre>
<h3 id="heading-typescript-compiler-tsc">TypeScript Compiler (tsc)</h3>
<p>TypeScript provides both type checking and transpilation capabilities:</p>
<pre><code class="lang-javascript">bash# Install TypeScript
npm install --save-dev typescript

# Create tsconfig.json
{
  <span class="hljs-string">"compilerOptions"</span>: {
    <span class="hljs-string">"target"</span>: <span class="hljs-string">"ES5"</span>,
    <span class="hljs-string">"module"</span>: <span class="hljs-string">"commonjs"</span>,
    <span class="hljs-string">"lib"</span>: [<span class="hljs-string">"ES2015"</span>, <span class="hljs-string">"DOM"</span>]
  }
}
</code></pre>
<h3 id="heading-modern-alternatives">Modern Alternatives</h3>
<p>Recent transpilers like SWC and esbuild offer significantly improved performance:</p>
<ul>
<li><p><strong>SWC</strong>: Written in Rust, provides 20x faster compilation than Babel</p>
</li>
<li><p><strong>esbuild</strong>: Go-based bundler with extremely fast transpilation</p>
</li>
<li><p><strong>Sucrase</strong>: Focuses on speed for modern browser targets</p>
</li>
</ul>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Polyfills and transpilers are two helpful solutions for modern JavaScript development across various browser environments. Transpilers are excellent at converting syntax, enabling developers to write modern JavaScript that runs on older engines. Polyfills provide runtime functionality by adding missing APIs and methods that older browsers lack.</p>
]]></content:encoded></item></channel></rss>