<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dhamith Kumara</title>
    <description>The latest articles on DEV Community by Dhamith Kumara (@bdhamithkumara).</description>
    <link>https://dev.to/bdhamithkumara</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%2F668172%2Fa3f991fb-3540-4a94-9c1a-1304b3887669.jpg</url>
      <title>DEV Community: Dhamith Kumara</title>
      <link>https://dev.to/bdhamithkumara</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bdhamithkumara"/>
    <language>en</language>
    <item>
      <title>Why have a flat Resume when you can have an OS? 🚀 Dive into BDK-OS</title>
      <dc:creator>Dhamith Kumara</dc:creator>
      <pubDate>Sat, 31 Jan 2026 07:06:03 +0000</pubDate>
      <link>https://dev.to/bdhamithkumara/why-have-a-flat-resume-when-you-can-have-an-os-dive-into-bdk-os-2dm2</link>
      <guid>https://dev.to/bdhamithkumara/why-have-a-flat-resume-when-you-can-have-an-os-dive-into-bdk-os-2dm2</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/new-year-new-you-google-ai-2025-12-31"&gt;New Year, New You Portfolio Challenge Presented by Google AI&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I am a passionate Full Stack Developer with over 2+ years of industrial experience and a deep seated love for building high performance, creative web applications. My journey in tech is driven by the challenge of transforming complex problems into elegant, interactive digital experiences.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Portfolio Expression
&lt;/h3&gt;

&lt;p&gt;With this portfolio, BDK-OS, I wanted to express more than just a list of skills. I wanted to showcase my ability to blend utility with creativity.&lt;/p&gt;

&lt;p&gt;By reimagining my professional profile as a fully functional, browser-based operating system, I hope to demonstrate,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Technical Versatility - Managing complex global states, terminal logic, and game engines.&lt;/li&gt;
&lt;li&gt;Design Sensibility - A commitment to high-end aesthetics like glassmorphism and neon-retro UI.&lt;/li&gt;
&lt;li&gt;User Centric Innovation - Turning a "Read-only" resume into an "Interactive" experience where visitors can explore my bio, run my code, and even play a game.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am always looking for new challenges and opportunities to contribute to cutting edge projects. Let's build something amazing together!&lt;/p&gt;

&lt;h2&gt;
  
  
  Portfolio
&lt;/h2&gt;


&lt;div class="ltag__cloud-run"&gt;
  &lt;iframe height="600px" src="https://portfolio-type-01-465247809064.europe-west1.run.app"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;Building BDK-OS was an exercise in merging retro computing aesthetics with ultra modern web performance. My goal was to create a portfolio that felt like a "living" workspace rather than a static page.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Tech Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Framework - Next.js 16.1 (App Router) for high performance server side rendering and static generation.&lt;/li&gt;
&lt;li&gt;UI/Styling - Tailwind CSS for a utility first, highly customizable design system.&lt;/li&gt;
&lt;li&gt;Animations - Framer Motion to power the fluid window transitions, dragging mechanics, and the "Progressbar95" game engine.&lt;/li&gt;
&lt;li&gt;Icons - Lucide React for a consistent, minimalist icon language.&lt;/li&gt;
&lt;li&gt;Deployment - Docker with a multi stage build, optimized for production using Next.js standalone output.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Design Decisions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The "OS" Concept - I chose a windowed desktop interface (BDK-OS) to showcase my versatility. It allows visitors to interact with my projects, bio, and a terminal as if they are exploring my digital brain.&lt;/li&gt;
&lt;li&gt;Glassmorphism &amp;amp; Neon - To make the "Retro" feel "Futuristic," I used heavy backdrop blurs (backdrop-blur-md), semi transparent blacks (bg-black/80), and neon blue accents. This creates a high end, premium feel.&lt;/li&gt;
&lt;li&gt;Interactive Terminal - The terminal isn't just for show, It features a simulated file system (bio.txt, projects.md), command history navigation (using Arrow keys), and integration with the window manager to launch apps like the game.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Development Process
&lt;/h3&gt;

&lt;p&gt;I followed a component first architecture. I built a custom WindowManagerContext to handle the state of all open, minimized, and maximized windows globally. This allowed for features like "focus tracking" (bringing the last clicked window to the front) and "one click maximizing."&lt;/p&gt;

&lt;h3&gt;
  
  
  Google AI Tools Used
&lt;/h3&gt;

&lt;p&gt;This project was built with the assistance of Google Antigravity (powered by Gemini models). Specifically, I used AI to,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Architecture Design - Designing the global state management for the windowing system and terminal logic.&lt;/li&gt;
&lt;li&gt;Complex Logic - Developing the collision detection and spawning algorithms for the "Progressbar95" terminal game.&lt;/li&gt;
&lt;li&gt;Creative Assets - Generating the custom BDK-OS Favicon using Gemini’s integrated image generation capabilities.&lt;/li&gt;
&lt;li&gt;DevOps Optimization - Crafting a production ready Dockerfile and configuring Next.js standalone output for seamless deployment.&lt;/li&gt;
&lt;li&gt;SEO &amp;amp; Metadata - Automating the generation of OpenGraph tags and professional descriptions to improve the portfolio's discoverability.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I'm Most Proud Of
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Breathing New Life into a Classic&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;The feature I am most excited about is the Progressbar95 game integration. I took the core concept of the classic retro game and reimagined it as a fully playable experience within my portfolio.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Technical Achievement - Building a real time game engine inside a React component. I used Framer Motion to handle high performance animations for falling segments and collision detection between the "catcher" and the dropping bars.&lt;/li&gt;
&lt;li&gt;The "Easter Egg" Feel - While optional, this feature serves as a tribute to the legacy of OS design that inspired the rest of the site. It's more than just a game; it's a demonstration of how I can apply technical logic to create fun, engaging user experiences.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;The Custom Window Management System&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Rather than using a standard layout library, I built a custom Window Manager from the ground up.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Depth and Focus - I implemented a dynamic Z index system that tracks which window the user is interacting with, automatically bringing it to the "front" (just like a real OS).&lt;/li&gt;
&lt;li&gt;Desktop Workflow: Integrating drag and drop mechanics, window minimizing to the taskbar, and a full screen maximize toggle. Achieving this level of desktop native feel in a web browser using WindowManagerContext was a significant technical milestone for me.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;The Command Line Soul&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;I am particularly proud of the Terminal's integration with my data.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's not a static text box it has a simulated file system that reads from my actual project data (projects.ts) and biography.&lt;/li&gt;
&lt;li&gt;Implementing Command History (using up/down arrows) and unique commands like game to launch other parts of the UI creates a cohesive experience for developer minded visitors.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>googleaichallenge</category>
      <category>portfolio</category>
      <category>gemini</category>
    </item>
    <item>
      <title>More Than a T-Shirt: My 3-Year Battle to Win Hacktoberfest</title>
      <dc:creator>Dhamith Kumara</dc:creator>
      <pubDate>Mon, 13 Oct 2025 17:50:35 +0000</pubDate>
      <link>https://dev.to/bdhamithkumara/more-than-a-t-shirt-my-3-year-battle-to-win-hacktoberfest-41no</link>
      <guid>https://dev.to/bdhamithkumara/more-than-a-t-shirt-my-3-year-battle-to-win-hacktoberfest-41no</guid>
      <description>&lt;p&gt;Everyone talks about the Hacktoberfest event, but they rarely talk about what you actually get after winning it, right?&lt;/p&gt;

&lt;p&gt;I've been joining Hacktoberfest since 2022. In the early days, all I could get was the participation badge 😉. &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%2F2kpxtbx1ljuobtbon0dl.jpg" 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%2F2kpxtbx1ljuobtbon0dl.jpg" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I joined the event again in 2023, but I still only managed to get the participation badge. &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%2Fvhrykdho5apkslvdynja.jpg" 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%2Fvhrykdho5apkslvdynja.jpg" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, I learned a lot during all those events. Anyway, I joined the event in 2024 as well. Although I couldn't win, I created 4 PRs and got 4 badges.&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%2Fklj318oi9oz3f66pgygq.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%2Fklj318oi9oz3f66pgygq.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&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%2F38cz7fzg22si0hjepw2b.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%2F38cz7fzg22si0hjepw2b.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&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%2F7erextehfzwx8z240gwa.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%2F7erextehfzwx8z240gwa.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&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%2Ftj94axihu0peo7jo89bp.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%2Ftj94axihu0peo7jo89bp.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But I still wasn't able to win the main event.&lt;/p&gt;

&lt;p&gt;However, for Hacktoberfest 2025, I joined with a lot of planning. I was completely in the zone, finding repositories and issues days before the event started. I knew that with thousands of participants worldwide, getting my PRs accepted would be a race against the clock. 😌&lt;/p&gt;

&lt;p&gt;I had created 5 of my PRs by the morning of October 1st, the very moment the event started. I quickly realized that winning a global event against such intense competition is incredibly challenging 😪. Anyway, by the end of the first two days, I had created all 6 of my PRs. But that was just the start. Just creating PRs isn't enough; the project maintainers need to review and merge them. And with the 7-day review window to check for spam or low-quality contributions, it’s a long, nerve-wracking process to get final acceptance.&lt;/p&gt;

&lt;p&gt;Anyway, after 3 years of hard work and persistence, I finally managed to achieve the goal I set, winning Hacktoberfest event! &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%2Fcj4o3xw2jd0os66v5ebk.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%2Fcj4o3xw2jd0os66v5ebk.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What did I get? 😎 More than anything, I learned a lot of new things. You gain a completely different experience when working on many diverse projects.&lt;/p&gt;

&lt;p&gt;For winning the event, I received a tree as a gift from Hacktoberfest's tree plantation initiative 😋. I also received a limited edition t-shirt.&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%2Fy6g9zxa49o1hsyrn752v.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%2Fy6g9zxa49o1hsyrn752v.png" alt=" " width="783" height="577"&gt;&lt;/a&gt;&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%2F742tft6n6t4uodaus7go.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%2F742tft6n6t4uodaus7go.png" alt=" " width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Reading this, you might think, "Well, you can buy these things with money."&lt;/p&gt;

&lt;p&gt;But that's not the truth. With all this, we can learn new things and gain new experience. This might be a big deal for me, but it might be a small thing for you. 😌&lt;/p&gt;

&lt;p&gt;I, too, would love to see more guys and girls contributing to open-source projects on social media someday in the future.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>hacktoberfest</category>
      <category>discuss</category>
      <category>hackathon</category>
    </item>
    <item>
      <title>How to Generate sitemap.xml in Next.js for Better SEO</title>
      <dc:creator>Dhamith Kumara</dc:creator>
      <pubDate>Sun, 21 Sep 2025 12:42:49 +0000</pubDate>
      <link>https://dev.to/bdhamithkumara/how-to-generate-sitemapxml-in-nextjs-for-better-seo-52i3</link>
      <guid>https://dev.to/bdhamithkumara/how-to-generate-sitemapxml-in-nextjs-for-better-seo-52i3</guid>
      <description>&lt;p&gt;Search engines like Google and Bing rely on sitemaps to crawl your site effectively. If you're using Next.js you can generate a dynamic sitemap to keep search engines up to date automatically.&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%2Fo3edawo2nuupo7pbgjq7.gif" 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%2Fo3edawo2nuupo7pbgjq7.gif" alt="Happy Big Lebowski GIF" width="400" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This guide will cover,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What a sitemap is and why it matters&lt;/li&gt;
&lt;li&gt;How sitemaps impact SEO&lt;/li&gt;
&lt;li&gt;The anatomy of a sitemap.xml file&lt;/li&gt;
&lt;li&gt;Splitting Large Sitemaps with Index Files&lt;/li&gt;
&lt;li&gt;Automating Sitemap Generation in Next.js with next-sitemap&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What a sitemap is and why it matters
&lt;/h2&gt;

&lt;p&gt;A sitemap is simply a list of all important URLs on your website, expressed in XML format. It acts as a "roadmap" for search engines, showing them where your content lives and when it last changed.&lt;/p&gt;

&lt;p&gt;Key benefits,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensures new pages are discovered quickly&lt;/li&gt;
&lt;li&gt;Helps index deep content (blog posts, E - commerce products, dynamic pages)&lt;/li&gt;
&lt;li&gt;Provides metadata (last modified date, change frequency, priority)&lt;/li&gt;
&lt;li&gt;Allows you to prioritize content for crawling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even though Google can discover URLs through links, a sitemap acts like a direct invitation to crawl every page you want indexed.&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%2Fe7wnllf63ympjicqti39.gif" 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%2Fe7wnllf63ympjicqti39.gif" alt="Sherlock Holmes Look GIF" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Sitemaps Impact SEO
&lt;/h2&gt;

&lt;p&gt;A sitemap doesn't directly improve rankings, but it makes it much easier for search engines to discover, crawl, and index your content. That can indirectly improve your SEO because your pages get into the index faster and more completely.&lt;/p&gt;

&lt;p&gt;Key impacts,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster indexing of new content - (When you publish new pages or update old ones, search engines see them immediately if they’re in your sitemap.)&lt;/li&gt;
&lt;li&gt;Improved coverage - (Large or deep sites (with many categories or paginated content) can be hard to crawl through links alone. A sitemap tells Google where everything is.)&lt;/li&gt;
&lt;li&gt;Crawl efficiency - (Search engines have a "crawl budget" for each site. A sitemap helps them spend it more wisely by pointing only to canonical, important URLs.)&lt;/li&gt;
&lt;li&gt;Metadata signals - (The &lt;code&gt;&amp;lt;lastmod&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;changefreq&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;priority&amp;gt;&lt;/code&gt; tags provide hints about how often a page changes and how important it is. Google treats them as advisory, but they still help guide crawling.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of a sitemap as a road map you hand to search engines. It doesn't guarantee rankings, but it makes sure the crawler doesn't miss any of your roads.&lt;/p&gt;

&lt;h2&gt;
  
  
  The anatomy of a sitemap.xml file
&lt;/h2&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%2Fuv03hms1picu0rj9bi0k.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%2Fuv03hms1picu0rj9bi0k.png" alt="The anatomy of a sitemap.xml file" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;loc&amp;gt;&lt;/code&gt; - URL of the page&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;lastmod&amp;gt;&lt;/code&gt; - last modification date&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;changefreq&amp;gt;&lt;/code&gt; - how often the content changes (optional)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;priority&amp;gt;&lt;/code&gt; - relative importance (optional)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Splitting Large Sitemaps with Index Files
&lt;/h2&gt;

&lt;p&gt;If your site has more than 50,000 URLs or your XML file is over 50 MB, you must split it into multiple sitemaps and create a sitemap index.&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%2Fp33ikyhqv3u0016q0px7.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%2Fp33ikyhqv3u0016q0px7.png" alt="Splitting Large Sitemaps " width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each child sitemap then lists a portion of your URLs. Search engines crawl the index file and automatically discover all child sitemaps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automating Sitemap Generation in Next.js with next-sitemap
&lt;/h2&gt;

&lt;p&gt;Manually crafting a sitemap.xml route can be overkill when your site already has dozens or hundreds of pages. The next-sitemap package takes care of the heavy lifting by generating a valid sitemap (and optional robots.txt) automatically during your build process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;Add the package to your project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install next-sitemap
# or
yarn add next-sitemap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set Up Configuration
&lt;/h3&gt;

&lt;p&gt;Create a file called next-sitemap.config.js in your project root and define how your sitemap should behave.&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%2Fubyifgcq43bwcp6nyvli.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%2Fubyifgcq43bwcp6nyvli.png" alt="Set Up Configuration" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Update your build script to run next-sitemap right after next build.&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%2Fni9lut4wzv67jy3eda8k.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%2Fni9lut4wzv67jy3eda8k.png" alt="Update your build script" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now every time you run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the package will output&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;public/sitemap.xml (or several if your site is huge)&lt;/li&gt;
&lt;li&gt;public/robots.txt&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;An up to date sitemap is one of the simplest yet most effective ways to help search engines understand your site's structure. By letting the next-sitemap package generate it automatically, you'll ensure every important page is discoverable and indexed quickly.&lt;/p&gt;

&lt;p&gt;For small sites, a manual sitemap gives you complete control. For larger or frequently changing sites, the built -in App Router feature or next-sitemap can automate the process and remove maintenance overhead.&lt;/p&gt;

&lt;p&gt;Once your sitemap is in place, don’t forget to &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Submit it to Google Search Console and Bing Webmaster Tools&lt;/li&gt;
&lt;li&gt;Keep your base URL and metadata accurate&lt;/li&gt;
&lt;li&gt;Regenerate it on every deploy to reflect new content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Following these steps will give your Next.js project stronger SEO and smoother crawling. Making it easier for search engines (and your audience) to find your content faster.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>discuss</category>
    </item>
    <item>
      <title>The Power of "^" in package.json</title>
      <dc:creator>Dhamith Kumara</dc:creator>
      <pubDate>Sat, 30 Aug 2025 10:50:36 +0000</pubDate>
      <link>https://dev.to/bdhamithkumara/the-power-of-in-packagejson-4pb7</link>
      <guid>https://dev.to/bdhamithkumara/the-power-of-in-packagejson-4pb7</guid>
      <description>&lt;p&gt;If you've ever peeked into your package.json file when working with Next.js (or any JavaScript framework), you’ve probably noticed something like this,&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%2Fsyt98ww63ss9480vi3ez.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%2Fsyt98ww63ss9480vi3ez.png" alt="dependencies" width="522" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At first glance, it's just a version number with a little caret &lt;code&gt;^&lt;/code&gt;. Seems harmless, right? But that tiny symbol can determine whether your app runs smoothly in production or suddenly breaks after deployment.&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%2Fuxzeu61bjkimz5k7lttk.gif" 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%2Fuxzeu61bjkimz5k7lttk.gif" alt="Excuse Me Reaction GIF by One Chicago" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This article takes a deep dive into the &lt;code&gt;^&lt;/code&gt; symbol in package.json,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it actually means (SemVer).&lt;/li&gt;
&lt;li&gt;The difference between "&lt;code&gt;^14.2.0&lt;/code&gt;" and "&lt;code&gt;14.2.0&lt;/code&gt;".&lt;/li&gt;
&lt;li&gt;Why deployments (like on AWS EC2) sometimes install different versions than your local environment.&lt;/li&gt;
&lt;li&gt;The pros and cons of using &lt;code&gt;^&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Best practices for keeping your Next.js projects stable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end, you’ll know exactly when to embrace &lt;code&gt;^&lt;/code&gt; and when to avoid it.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. What is Semantic Versioning (SemVer)?
&lt;/h2&gt;

&lt;p&gt;Most npm packages (including Next.js) follow semantic versioning written as,&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%2F6frq1q7qosauouco5euv.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%2F6frq1q7qosauouco5euv.png" alt="semantic versioning" width="640" height="218"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example &lt;code&gt;14.2.0&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MAJOR ➮ Breaking changes (&lt;code&gt;14.x.x&lt;/code&gt; ➝ &lt;code&gt;15.x.x&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;MINOR ➮ New features, backwards-compatible (&lt;code&gt;14.2.x&lt;/code&gt; ➝ &lt;code&gt;14.3.x&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;PATCH ➮ Bug fixes, backwards-compatible (&lt;code&gt;14.2.0&lt;/code&gt; ➝ &lt;code&gt;14.2.1&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The idea is that you can safely upgrade patch and usually minor versions without breaking your app.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. What Does the &lt;code&gt;^&lt;/code&gt; Symbol Do?
&lt;/h2&gt;

&lt;p&gt;In npm, ^ is a version range operator. It says,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Install the latest version compatible with this one.&lt;/p&gt;
&lt;/blockquote&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%2Frbqq449xkc96pbca2fo7.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%2Frbqq449xkc96pbca2fo7.png" alt="Common package.json Version Declarations" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So when you type,&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%2Fzm9o1nseabrc5lmffcn0.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%2Fzm9o1nseabrc5lmffcn0.png" alt="npm install" width="640" height="208"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;npm doesn't necessarily install the exact version listed. If you're using &lt;code&gt;^&lt;/code&gt;, it will pick the latest matching version that fits the range.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Why Deployments Sometimes Surprise You
&lt;/h2&gt;

&lt;p&gt;Here's a common story,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You run npm install locally. Your next version resolves to 14.2.0.&lt;/li&gt;
&lt;li&gt;You deploy to AWS EC2. During npm install, the server pulls 14.3.1 because it's the newest compatible release under ^14.2.0.&lt;/li&gt;
&lt;li&gt;Suddenly, your production behaves differently than your local machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This happens because,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Without a lockfile (package-lock.json, yarn.lock, or pnpm-lock.yaml), npm resolves dependencies fresh every time, possibly grabbing a newer version.&lt;/li&gt;
&lt;li&gt;With a lockfile committed, deployments should match your local environment exactly even with ^.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So if you've ever seen EC2 "mysteriously" use a newer Next.js version, the culprit is almost always a missing or ignored lockfile combined with the caret operator.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Pros and Cons of Using &lt;code&gt;^&lt;/code&gt;
&lt;/h2&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%2F8bmv7im6snewtl2dbinu.jpg" 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%2F8bmv7im6snewtl2dbinu.jpg" alt="Pros and Cons" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. When to Use ^ vs Exact Versions
&lt;/h2&gt;

&lt;p&gt;Think of it as a tradeoff between stability and freshness,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use ^ for libraries that are safe and mature (like lodash, date-fns, or axios). These packages rarely break between minors.&lt;/li&gt;
&lt;li&gt;Pin exact versions for critical frameworks like next, react, or build tools especially in production apps. That way, you control when you upgrade.&lt;/li&gt;
&lt;/ul&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%2Fwk5ds2npyiooqvek7tqc.gif" 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%2Fwk5ds2npyiooqvek7tqc.gif" alt="Old Lady Wow GIF by Offline Granny" width="480" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;That little caret (^) in package.json is more powerful than it looks.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"^14.2.0" keeps your app automatically updated within the 14.x line (minor + patch updates).&lt;/li&gt;
&lt;li&gt;"14.2.0" locks you to one exact version, ensuring maximum stability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The real issue isn't the caret itself. It's how you manage installs. If you don't commit a lockfile or use npm ci, your deployments (like on EC2) may suddenly run a different version than your local machine.&lt;/p&gt;

&lt;p&gt;The key takeaway is balance,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Pin exact versions for critical frameworks like Next.js and React, where stability matters most.&lt;/li&gt;
&lt;li&gt;✅ Use ^ for smaller, safer libraries to benefit from automatic fixes.&lt;/li&gt;
&lt;li&gt;✅ Always commit your lockfile and use npm ci in deployments to prevent surprises.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of ^ as an autopilot mode. It can save time by keeping dependencies fresh, but without guardrails, it can take you somewhere you didn't plan to go.&lt;/p&gt;

&lt;p&gt;Mastering when to lock versions and when to allow flexibility will save you countless headaches and give you the best of both worlds stability in production, convenience in development.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>discuss</category>
      <category>learning</category>
      <category>development</category>
    </item>
    <item>
      <title>How to Hide API Endpoints in Next.js</title>
      <dc:creator>Dhamith Kumara</dc:creator>
      <pubDate>Sun, 24 Aug 2025 07:13:24 +0000</pubDate>
      <link>https://dev.to/bdhamithkumara/how-to-hide-api-endpoints-in-nextjs-4iij</link>
      <guid>https://dev.to/bdhamithkumara/how-to-hide-api-endpoints-in-nextjs-4iij</guid>
      <description>&lt;p&gt;In Next.js, securing sensitive data and preventing the exposure of API endpoints is critical for building secure web applications. When fetching data, the approach you choose direct or indirect determines whether API endpoints are visible in the browser's network tab. This article explores how to hide API endpoints in Next.js, using two Proof of Concept (POCs) examples to compare direct and indirect data fetching. We'll demonstrate how direct fetching keeps endpoints hidden and provide best practices for securing your Next.js app, based on a project using Next.js 15.5.0, React 19.1.0, and Supabase.&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%2Fn72yt124l1laoohnrz45.gif" 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%2Fn72yt124l1laoohnrz45.gif" alt=" " width="400" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Structure and Setup
&lt;/h2&gt;

&lt;p&gt;The examples in this article are based on a Next.js project with the following setup,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next.js (v 15.5.0)&lt;/li&gt;
&lt;li&gt;React (v 19.0.1)&lt;/li&gt;
&lt;li&gt;Supabase &lt;/li&gt;
&lt;li&gt;Directory Structure &lt;/li&gt;
&lt;/ul&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%2Fjp5n85lx616hp5lsghw4.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%2Fjp5n85lx616hp5lsghw4.png" alt="Directory Structure" width="800" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This setup uses a Supabase table named post with columns post (string) and keyword (string) to store and query data based on user-selected keywords. The POCs demonstrate fetching posts matching a selected keyword, highlighting the differences in endpoint exposure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding API Endpoint Exposure
&lt;/h2&gt;

&lt;p&gt;When you fetch data in a Next.js application, the method you use determines whether the data-fetching process is visible in the browser's network tab,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Indirect Fetching - Involves calling an API endpoint (e.g., a Next.js API route or external service) via HTTP requests, which are visible in the network tab, exposing the endpoint URL, request payload, and response data.&lt;/li&gt;
&lt;li&gt;Direct Fetching - Executes data fetching within the app, typically server-side, without creating a public API endpoint, making it invisible in the network tab.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hiding API endpoints is critical to prevent attackers from inspecting sensitive data, reverse-engineering your API, or exploiting unprotected endpoints. Let's examine both approaches using POCs that fetch data from a Supabase database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Indirect Data Fetching (Exposed API Endpoints)
&lt;/h2&gt;

&lt;p&gt;Indirect fetching involves calling a Next.js API route or external service from the client side, creating visible HTTP requests. Here’s a POC demonstrating this approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  POC - Indirect Fetching with an API Route
&lt;/h2&gt;

&lt;p&gt;In this POC, a Next.js app fetches posts from a Supabase database by calling an API route &lt;code&gt;(/api/getPost)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/bdhamithkumara/indirect-fetch" rel="noopener noreferrer"&gt;repo&lt;/a&gt;&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%2Fopi7adute2bkrbo6brux.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%2Fopi7adute2bkrbo6brux.png" alt="Indirect Fetching" width="800" height="1332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Observations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Exposed Endpoint - The /api/getPost endpoint is publicly accessible and appears in the browser’s network tab. The request (e.g., POST /api/getPost with payload { keyword: selectedValue }) and response (e.g., { success: true, data: [...] }) are visible.&lt;/li&gt;
&lt;li&gt;Security Risk - Without authentication or rate limiting, anyone can call this endpoint, potentially exposing sensitive data or allowing abuse (e.g., brute-forcing keywords).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Direct Data Fetching (Hiding API Endpoints)
&lt;/h2&gt;

&lt;p&gt;Direct fetching involves retrieving data within the Next.js app, typically server side, without exposing an API endpoint. This approach leverages Next.js's Server Components or server actions to keep data fetching internal.&lt;/p&gt;

&lt;h2&gt;
  
  
  POC - Direct Fetching with Server Actions
&lt;/h2&gt;

&lt;p&gt;In this POC, the app fetches posts from Supabase using a server action, with no public API endpoint.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/bdhamithkumara/direct-fetch" rel="noopener noreferrer"&gt;repo&lt;/a&gt;&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%2Fjciio2zb3bu10ejhjjvi.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%2Fjciio2zb3bu10ejhjjvi.png" alt="Direct Fetching" width="800" height="2333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Observations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No Endpoint Exposure - The getPost function is a server action, executed server-side via Next.js's App Router. No public API endpoint is created, so nothing appears in the network tab related to the data fetch.&lt;/li&gt;
&lt;li&gt;Security Benefit - Sensitive operations (e.g., Supabase queries with API keys) remain server side, hidden from the client, reducing the risk of exposing implementation details.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Direct Fetching Hides API Endpoints
&lt;/h2&gt;

&lt;p&gt;In the direct fetching POC, the "use server" directive ensures that the getPost function runs on the server, not the client. When the client-side component calls callGetPostData, Next.js handles the request internally as a server action, serializing the response into the JavaScript bundle or rendered HTML. This process,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Eliminates the need for a public API endpoint.&lt;/li&gt;
&lt;li&gt;Prevents network requests from appearing in the browser's network tab.&lt;/li&gt;
&lt;li&gt;Keeps sensitive data (e.g., Supabase credentials) secure on the server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In contrast, the indirect fetching POC's /api/getPost endpoint is a standard HTTP API, accessible to anyone unless secured, and its requests are visible in the network tab.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for Hiding API Endpoints
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prioritize Server-Side Fetching - Use Server Components or server actions for sensitive data operations to avoid exposing endpoints.&lt;/li&gt;
&lt;li&gt;Secure API Routes - If using indirect fetching, implement authentication, rate-limiting, and input validation.&lt;/li&gt;
&lt;li&gt;Hide Sensitive Data - Store Supabase credentials and other secrets in .env.local files, as done in the POCs.&lt;/li&gt;
&lt;li&gt;Monitor Network Exposure - Test your app's network tab to ensure no sensitive endpoints or data are visible.&lt;/li&gt;
&lt;li&gt;Use Incremental Static Regeneration (ISR) - For static sites, fetch data at build time or during revalidation to avoid runtime API calls.&lt;/li&gt;
&lt;/ul&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%2F0kf2r54f489hwge0xobu.gif" 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%2F0kf2r54f489hwge0xobu.gif" alt=" " width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Hiding API endpoints in Next.js is achievable by favoring direct data fetching with server actions or Server Components, as demonstrated in the direct fetching POC using Next.js 15.5.0, React 19.1.0, and Supabase. This approach keeps data retrieval internal, preventing endpoint exposure in the browser's network tab and enhancing security. In contrast, indirect fetching, as shown in the API route POC, exposes endpoints, requiring additional security measures like authentication or middleware. By leveraging direct fetching for sensitive operations and securing any necessary API routes, you can build secure, performant Next.js applications that protect your data and implementation details.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>discuss</category>
      <category>learning</category>
    </item>
    <item>
      <title>Exploring git cherry and git cherry-pick</title>
      <dc:creator>Dhamith Kumara</dc:creator>
      <pubDate>Sun, 10 Aug 2025 18:05:21 +0000</pubDate>
      <link>https://dev.to/bdhamithkumara/exploring-git-cherry-and-git-cherry-pick-59gn</link>
      <guid>https://dev.to/bdhamithkumara/exploring-git-cherry-and-git-cherry-pick-59gn</guid>
      <description>&lt;p&gt;Git is the lifeblood of modern software development. From hobbyists working on personal projects to massive organizations managing enterprise codebases, Git provides the version control backbone. While the learning curve can be steep at first, most developers quickly become familiar with a handful of commands and workflows. But Git is far richer than what most of us use on a daily basis.&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%2Faf9slks7zrc7b448j4kw.gif" 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%2Faf9slks7zrc7b448j4kw.gif" alt="count gif" width="500" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Did you know Git has over 150 commands available through its CLI? That number jumps even higher if you count all the flags, aliases, and plumbing commands under the hood. Most developers only scratch the surface using perhaps a dozen commands regularly. That's fine for basic workflows, but understanding some of Git's lesser known capabilities can help you become more effective, avoid pitfalls, and better manage complex codebases.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is git cherry?
&lt;/h2&gt;

&lt;p&gt;git cherry is a comparison tool. It helps you determine which commits in one branch are missing from another, based on content (not just commit hashes).&lt;/p&gt;

&lt;h2&gt;
  
  
  When Would You Use It?
&lt;/h2&gt;

&lt;p&gt;Imagine you're working on a long lived feature branch and want to know which of its commits are not yet in the main branch. Or maybe you're preparing a release and want to ensure nothing was forgotten from a development branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Syntax
&lt;/h2&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%2Fq02dp1ccowpnoi6jbsw7.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%2Fq02dp1ccowpnoi6jbsw7.png" alt="git cherry code" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;Unlike git log, which compares by commit hash, git cherry compares patches. So if two commits have different hashes but the same content (a cherry-pick, for example), git cherry considers them duplicates.&lt;/p&gt;

&lt;p&gt;This makes git cherry ideal for code review and release preparation tasks.&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%2Fjp59c6z2e5oz7aojd44u.gif" 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%2Fjp59c6z2e5oz7aojd44u.gif" alt="Oh I Get It Jimmy Fallon GIF " width="480" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is git cherry-pick?
&lt;/h2&gt;

&lt;p&gt;While git cherry is a read only diagnostic tool, git cherry-pick modifies your codebase. It allows you to take one or more specific commits from another branch and apply them to your current branch—without merging everything from that source branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Would You Use It?
&lt;/h2&gt;

&lt;p&gt;Let's say a developer fixed a critical bug on a dev branch, but the main branch also needs that fix right now. Instead of merging all of dev, you cherry-pick just that one bug fix commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Syntax
&lt;/h2&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%2Fzfuktwbp8uti3lhaglrr.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%2Fzfuktwbp8uti3lhaglrr.png" alt="cherry-pick syntax" width="788" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Important Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Cherry-picking creates new commit hashes, even though the content is the same.&lt;/li&gt;
&lt;li&gt;Cherry-picking multiple commits? Order matters! Pick them in the sequence they were created.&lt;/li&gt;
&lt;li&gt;Conflicts may arise if the codebase has changed significantly since the original commit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  git cherry vs git cherry-pick
&lt;/h2&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%2Fysj7ob10gpszdxqakxx8.jpg" 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%2Fysj7ob10gpszdxqakxx8.jpg" alt="git cherry vs git cherry-pick" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A step by step guide to understanding how it works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1 - Create a New Repository
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir git-cherry-demo
cd git-cherry-demo
git init -b main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2 - Add an Initial Commit
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "# Git Cherry Demo" &amp;gt; README.md
git add README.md
git commit -m "Initial commit with README"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3 - Create the hero-section Branch
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout -b hero-section
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4 - Add a Unique Commit
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "This is unique to hero-section branch" &amp;gt;&amp;gt; README.md
git add README.md
git commit -m "Add unique content to README in hero-section"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5 - Add a Commit That Will Be Duplicated
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "This is shared content" &amp;gt;&amp;gt; README.md
git add README.md
git commit -m "Add shared content to README"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 6 - Cherry-pick That Commit into main
&lt;/h3&gt;

&lt;p&gt;First, find the commit hash for the "shared content" commit&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git log --oneline
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F9f0xbqwzxyejg1l6as5v.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%2F9f0xbqwzxyejg1l6as5v.png" alt="output" width="792" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy the hash (a1549a7) and run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout main
git cherry-pick a1549a7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 7 - Compare Branches with git cherry
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git cherry main hero-section
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see something like&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%2F1ru7qyn1djspnph1ptyg.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%2F1ru7qyn1djspnph1ptyg.png" alt="output2" width="718" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;If Git were a toolbox, most developers stick to the hammer, screwdriver, and tape measure. But tucked away inside are precision tools like git cherry and git cherry pick that can help in nuanced, high stakes situations like release branches, hotfixes, and cross-team merges.&lt;/p&gt;

&lt;p&gt;Learning to wield these commands doesn't just make you a better Git user. It makes you a more capable collaborator, a faster debugger, and a smarter code reviewer.&lt;/p&gt;

&lt;p&gt;So next time you're facing a tangled merge problem or wondering what's unique in a feature branch, try reaching for git cherry or git cherry-pick. You might find that small, precise changes can make a world of difference.&lt;/p&gt;

</description>
      <category>git</category>
      <category>beginners</category>
      <category>discuss</category>
      <category>learning</category>
    </item>
    <item>
      <title>How I Landed My Internship as an Undergraduate Student</title>
      <dc:creator>Dhamith Kumara</dc:creator>
      <pubDate>Sat, 26 Jul 2025 18:31:14 +0000</pubDate>
      <link>https://dev.to/bdhamithkumara/how-i-landed-my-internship-as-an-undergraduate-student-53ij</link>
      <guid>https://dev.to/bdhamithkumara/how-i-landed-my-internship-as-an-undergraduate-student-53ij</guid>
      <description>&lt;p&gt;Hi, I'm Dhamith, a software engineer with over 2.5 years of experience. But back when I was an undergraduate, I faced the same challenge many students face today, finding an internship. These days, it's tough. There's lots of competition, few responses, and endless applications. That's exactly why I'm sharing my story. I didn't land my internship through a job portal or by sending out resumes. It came from something completely different. Here's how it happened.&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%2Frhwdc1k8k6qnrxoag7vs.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%2Frhwdc1k8k6qnrxoag7vs.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the beginning, I built a few hobby projects just for fun. Simple things I was curious about or wanted to try. I didn't expect much from them, but I shared them anyway on social media. At first, I posted my work everywhere Twitter, Facebook, and LinkedIn. But after a while, I started noticing something, LinkedIn was where my work was getting the most attention. People in the tech industry were more active there, and my posts were reaching the right audience. So even though I continued sharing on other platforms, I began focusing more on LinkedIn. &lt;/p&gt;

&lt;p&gt;At first, I told myself, "Now you have the platform to share your progress  but you don't really have a clear plan." I knew I wanted to build and grow, but I wasn't sure where to begin. So I started with what I could simple landing pages using React, and I shared them online. Then one day, while scrolling through Twitter, I noticed developers consistently posting daily updates using the hashtag #100DaysOfCode. At first, I didn't even realize it was a public challenge. I thought it was just something people were doing independently. But the more I saw, the more inspired I became. That’s when I decided to commit to the #100DaysOfCode challenge myself.&lt;/p&gt;

&lt;p&gt;When I started the challenge, I still didn't have a clear roadmap. So on Day 1, I created a simple loading animation using just HTML and CSS. From there, I kept going. I completed several mini projects using HTML, CSS, JavaScript, and later moved on to React and MongoDB. You might find it hard to believe, but as an undergraduate student juggling lectures, assignments, and limited time, I still made it work. While others used weekends to relax, I used mine to build. On many nights, I stayed up late just to complete a project. Every single day, I challenged myself to create and share something new for the #100DaysOfCode.&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%2F37trw8lofivc2re64arp.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%2F37trw8lofivc2re64arp.png" alt=" We are hiring message " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As I continued sharing my progress through the #100DaysOfCode challenge, something completely unexpected happened. One night, I received a message on LinkedIn that caught me by surprise "We are hiring" The message included openings for roles like ASE, SE, and SSE. I wasn’t actively job hunting, but I replied and mentioned that I was currently looking for an internship as an undergraduate. To my surprise, they were open to it. After a few more messages, they invited me to take part in a technical interview and a coding assessment. I gave it my best, and not long after, they officially offered me an internship.&lt;/p&gt;

&lt;p&gt;After completing the internship, my team lead gave me feedback that truly stayed with me. She said, "We were really impressed by your work. That's why we reached out to you through LinkedIn." That one sentence confirmed everything I had believed while doing the #100DaysOfCode challenge. All those late nights, daily posts, and small projects added up. It wasn't luck. It was the result of showing up every day and sharing my progress publicly. That was the moment I truly realized how powerful consistency and building in public can be.&lt;/p&gt;

&lt;p&gt;So here's my advice to anyone trying to land an internship, Don't just do what everyone else is doing. Try to create something unique, something so impressive that when people see it, their first reaction is "Wow!" Share your progress on the right platforms, where your work can be noticed by the right audience. And most importantly, never give up. Consistency, creativity, and persistence are the keys to standing out and turning opportunities your way.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Mastering SSG, SSR, ISR, and CSR in Next.js</title>
      <dc:creator>Dhamith Kumara</dc:creator>
      <pubDate>Sat, 19 Jul 2025 18:34:50 +0000</pubDate>
      <link>https://dev.to/bdhamithkumara/mastering-ssg-ssr-isr-and-csr-in-nextjs-19bi</link>
      <guid>https://dev.to/bdhamithkumara/mastering-ssg-ssr-isr-and-csr-in-nextjs-19bi</guid>
      <description>&lt;p&gt;Next.js is far more than a React framework, it’s a versatile hybrid rendering engine granting precise control over page creation and delivery. In this detailed guide, we’ll explore the distinctions among Next.js's four primary rendering strategies, their effects on performance and SEO, advanced use cases, and provide code examples for each approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  Next.js Rendering Strategies
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;SSG - Static Site Generation&lt;/li&gt;
&lt;li&gt;SSR - Server-Side Rendering&lt;/li&gt;
&lt;li&gt;ISR - Incremental Static Regeneration&lt;/li&gt;
&lt;li&gt;CSR - Client-Side Rendering&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. Static Site Generation (SSG)
&lt;/h2&gt;

&lt;p&gt;With SSG, your pages are generated at build time, turned into HTML, and served via a CDN. It’s blazing fast because there’s no server computation on each request.&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%2Fyftnekn958859tbuvqyy.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%2Fyftnekn958859tbuvqyy.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scenarios - Weblogs, Advertising sites, Reference manuals, Creative showcases&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%2F3iwm8hgfrbcn802bfndt.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%2F3iwm8hgfrbcn802bfndt.png" alt=" " width="800" height="844"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Server Side Rendering (SSR)
&lt;/h2&gt;

&lt;p&gt;In SSR, the HTML is generated on the server for every request. This ensures that users always get fresh content, but with a performance cost.&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%2Fytbfa4d8b3hjte7l05is.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%2Fytbfa4d8b3hjte7l05is.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scenarios - Dashboards, Authenticated user pages, Search results, A/B testing pages&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%2F5q91rfm8amkw51birynu.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%2F5q91rfm8amkw51birynu.png" alt=" " width="800" height="707"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Incremental Static Regeneration (ISR)
&lt;/h2&gt;

&lt;p&gt;Incremental Static Regeneration (ISR) combines the advantages of static and dynamic rendering, delivering static HTML pages generated at build time that can be updated on-demand without redeploying the entire site. With ISR, you set a revalidation interval (in seconds), and Next.js automatically rebuilds the page in the background when a request is received after the specified time expires. This ensures subsequent visitors receive the updated page seamlessly.&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%2Fmzpzt6ctr1hh67w3uz7g.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%2Fmzpzt6ctr1hh67w3uz7g.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scenarios - Product pages, News articles, Catalogs, Events and conference sites&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%2F4p6y3jh1pbu9tgv1bpk5.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%2F4p6y3jh1pbu9tgv1bpk5.png" alt=" " width="800" height="876"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Client Side Rendering (CSR)
&lt;/h2&gt;

&lt;p&gt;CSR happens entirely in the browser using React. The initial page is a basic HTML shell, and content is fetched and rendered after page load using APIs or React hooks.&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%2Fq7ig00clk5pz3rk34bfx.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%2Fq7ig00clk5pz3rk34bfx.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scenarios - Admin panels, Dashboards, Interactive charts, Private areas of apps&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%2Fr22u9m64kreil5avacgc.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%2Fr22u9m64kreil5avacgc.png" alt=" " width="800" height="876"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Next.js empowers developers with flexible rendering strategies that can be tailored to any application's needs whether it’s SEO driven marketing pages, dynamic dashboards, or hybrid apps that do both.&lt;/p&gt;

&lt;p&gt;Understanding when to use SSG, SSR, ISR, or CSR is critical for building fast, scalable, and user friendly web experiences. Each method has its strengths,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SSG offers speed and simplicity.&lt;/li&gt;
&lt;li&gt;SSR provides up to date, dynamic content.&lt;/li&gt;
&lt;li&gt;ISR bridges the gap between static and dynamic.&lt;/li&gt;
&lt;li&gt;CSR enables rich interactivity and personalization.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of picking just one, modern Next.js projects often combine multiple strategies delivering static performance where possible and dynamic flexibility where needed.&lt;/p&gt;

&lt;p&gt;By mastering these techniques, you'll not only build better apps, you'll build smarter, faster, and more adaptable ones.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>nextjs</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Why You Should Never Commit Your .env File and How to Handle It Properly</title>
      <dc:creator>Dhamith Kumara</dc:creator>
      <pubDate>Sun, 08 Jun 2025 06:53:20 +0000</pubDate>
      <link>https://dev.to/bdhamithkumara/why-you-should-never-commit-your-env-file-and-how-to-handle-it-properly-2p85</link>
      <guid>https://dev.to/bdhamithkumara/why-you-should-never-commit-your-env-file-and-how-to-handle-it-properly-2p85</guid>
      <description>&lt;p&gt;Recently, while reviewing some undergraduate software projects, I stumbled upon a worrying trend. In several cases, students had included their .env files directly in their public repositories. Some even tried a workaround by uploading their .env files compressed inside a .env.rar archive, assuming this would somehow make it safer.&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%2Ff5o0b476k5sqok4nmnta.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%2Ff5o0b476k5sqok4nmnta.png" alt="sample .env expose " width="800" height="363"&gt;&lt;/a&gt;&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%2Fhvw2c0rrtcjt2p4twzn7.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%2Fhvw2c0rrtcjt2p4twzn7.png" alt="sample .env.rar expose " width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a classic example of a problem many new (and even experienced) developers underestimate: how to properly handle environment variables and sensitive configuration files in a project.&lt;/p&gt;

&lt;p&gt;If you’re building software, whether as a student, a freelancer, or part of a company, understanding the role of environment configuration and how to manage it securely is an essential skill. In this article, I’ll explain what .env files are, why they’re important, the mistakes people commonly make, how to fix accidents, and the right practices you should follow to handle them safely.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Exactly Is a &lt;code&gt;.env&lt;/code&gt; File?
&lt;/h2&gt;

&lt;p&gt;In software development, especially in web applications, your program often needs to connect to databases, access external APIs, or use secret tokens. Hardcoding these values directly in your source code is dangerous because anyone with access to your code would then have access to your sensitive credentials.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;.env&lt;/code&gt; file is a simple text file used to store environment variables for your application in a key value format.&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%2F5dk9xr16a4d00gsa6kpu.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%2F5dk9xr16a4d00gsa6kpu.png" alt=".env file example " width="800" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This file allows you to separate sensitive information from your codebase. Libraries like dotenv in Node.js or Python's python-dotenv can then load these variables into your application at runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Do Developers Use &lt;code&gt;.env&lt;/code&gt; Files?
&lt;/h2&gt;

&lt;p&gt;The main reason is &lt;strong&gt;security&lt;/strong&gt; and &lt;strong&gt;flexibility&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of embedding sensitive values directly into your source files, you place them inside a &lt;code&gt;.env&lt;/code&gt; file that’s read when the application starts. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can keep your code the same while changing your configurations depending on the environment (development, staging, production).&lt;/li&gt;
&lt;li&gt;It reduces the risk of accidentally exposing sensitive information in your codebase.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Imagine deploying a website where your database password is written inside your code file. Anyone with access to your source code repository would also have the credentials to access your database. This is exactly what &lt;code&gt;.env&lt;/code&gt; files help to avoid.&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%2Fnsd1duh7sbxmfg6e3w00.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%2Fnsd1duh7sbxmfg6e3w00.png" alt="Common Mistakes" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Common Mistakes People Make with &lt;code&gt;.env&lt;/code&gt; Files
&lt;/h2&gt;

&lt;p&gt;Unfortunately, as I saw in those student projects, &lt;code&gt;.env&lt;/code&gt; files often aren’t handled the way they should be. Let’s talk about the common mistakes I encountered.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.Committing .env Files to Public Repositories
&lt;/h3&gt;

&lt;p&gt;The most obvious and dangerous mistake is adding a &lt;code&gt;.env&lt;/code&gt; file to your version control system (like Git) and pushing it to a public repository. Doing this exposes your sensitive environment variables to anyone on the internet.&lt;/p&gt;

&lt;p&gt;Once secrets are exposed publicly, they can be harvested by bots within minutes, leading to stolen API keys, compromised databases, or unauthorized access to services.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.Compressing &lt;code&gt;.env&lt;/code&gt;Files into &lt;code&gt;.env.rar&lt;/code&gt; or &lt;code&gt;.zip&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Some students believed that compressing a &lt;code&gt;.env&lt;/code&gt; file into a &lt;code&gt;.rar&lt;/code&gt; or &lt;code&gt;.zip&lt;/code&gt; archive and uploading it to a repository was a secure workaround. Unfortunately, this offers no real security. Anyone can easily download and unzip these archives. Even worse, this practice often signals to attackers, "There’s something important inside here."&lt;/p&gt;

&lt;p&gt;Security by obscurity is no substitute for proper handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.Hardcoding Secrets Directly in Code
&lt;/h3&gt;

&lt;p&gt;Another rookie mistake is placing secrets directly into code files, like this&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%2F5luctlo9epfhfiunrwrs.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%2F5luctlo9epfhfiunrwrs.png" alt="example direct secreet key" width="800" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is just as unsafe as committing a &lt;code&gt;.env&lt;/code&gt; file and should be strictly avoided.&lt;/p&gt;

&lt;h2&gt;
  
  
  What To Do If You Accidentally Commit a .env File
&lt;/h2&gt;

&lt;p&gt;Mistakes happen, and if you’ve accidentally committed a &lt;code&gt;.env&lt;/code&gt; file to a public repository. Don’t panic, but act fast. Here’s exactly what you should do,&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Remove the File from the Repository History
&lt;/h3&gt;

&lt;p&gt;Simply deleting the file and committing the change isn’t enough because Git maintains a full history of all changes. You need to purge the file from the entire Git history using a tool like&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;git filter-branch (older method)&lt;/li&gt;
&lt;li&gt;BFG Repo-Cleaner (simpler, faster)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example using BFG&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%2Fz49o6zf4xfbuafaujxep.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%2Fz49o6zf4xfbuafaujxep.png" alt="Example using BFG" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then push your changes back&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%2F1u88x0lrlwdbwyr04du4.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%2F1u88x0lrlwdbwyr04du4.png" alt="Example push force" width="542" height="330"&gt;&lt;/a&gt;⚠ Be careful with force pushes, especially on shared projects ⚠&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Immediately Revoke and Rotate Exposed Secrets
&lt;/h3&gt;

&lt;p&gt;Assume that once the file was pushed, your secrets were compromised. Even if you deleted it moments later. API keys, database credentials, and tokens need to be invalidated and replaced with new ones.&lt;/p&gt;

&lt;p&gt;Go through your services (like AWS, Google Cloud, payment processors, email providers) and rotate any exposed credentials.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Notify Relevant Stakeholders
&lt;/h3&gt;

&lt;p&gt;If your accidental exposure affects shared infrastructure (like a production database, third-party services, or customer data access), inform your team or supervisor immediately so they can take precautionary measures.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Add &lt;code&gt;.env&lt;/code&gt; to &lt;code&gt;.gitignore&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Prevent the mistake from happening again by adding &lt;code&gt;.env&lt;/code&gt; to your &lt;code&gt;.gitignore&lt;/code&gt; file.&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%2Fnu3o9q34y92tyl9ojt5h.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%2Fnu3o9q34y92tyl9ojt5h.png" alt="correct way" width="751" height="718"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Should You Handle &lt;code&gt;.env&lt;/code&gt; Files Properly?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Always add &lt;code&gt;.env&lt;/code&gt; to your &lt;code&gt;.gitignore&lt;/code&gt; to exclude it from version control.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use a &lt;code&gt;.env.example&lt;/code&gt; to provide variable names without real values for others to follow.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Share actual &lt;code&gt;.env&lt;/code&gt; files securely via encrypted channels or secret management tools.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use CI/CD secret management features provided by platforms like GitHub Actions, GitLab, or Jenkins. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Regularly scan your codebase with tools like GitGuardian or Gitleaks to catch accidental secret commits early. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Periodically rotate your secrets even without incidents. It’s good operational hygiene.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Environment variables and &lt;code&gt;.env&lt;/code&gt; files are essential tools for separating sensitive configuration details from your application code. But with that convenience comes responsibility. Mishandling these files, whether by committing them to a public repository, hiding them in a &lt;code&gt;.rar&lt;/code&gt; archive, or hardcoding secrets can lead to serious security incidents.&lt;/p&gt;

&lt;p&gt;If you make a mistake, don’t waste time. Clean your repository history, rotate your secrets, and update your workflow to prevent future accidents.&lt;/p&gt;

&lt;p&gt;By adopting proper &lt;code&gt;.env&lt;/code&gt; management practices early in your development career, you not only protect your projects and credentials but also build habits that will serve you well in professional environments where security is taken seriously.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>discuss</category>
      <category>learning</category>
    </item>
    <item>
      <title>Sharing Data Across Next.js Components Using Context API and Hooks (with REST API Example)</title>
      <dc:creator>Dhamith Kumara</dc:creator>
      <pubDate>Thu, 05 Jun 2025 06:47:57 +0000</pubDate>
      <link>https://dev.to/bdhamithkumara/sharing-data-across-nextjs-components-using-context-api-and-hooks-with-rest-api-example-mma</link>
      <guid>https://dev.to/bdhamithkumara/sharing-data-across-nextjs-components-using-context-api-and-hooks-with-rest-api-example-mma</guid>
      <description>&lt;p&gt;When building React or Next.js applications, one of the most common tasks is sharing data between components. A simple way to do this is by passing data as props from a parent component down to its child components.&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%2Fr63bdx6g43i7v2fhehb5.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%2Fr63bdx6g43i7v2fhehb5.png" alt="example of data passing as props" width="712" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While this approach works fine for small projects, it quickly becomes problematic in larger, more complex applications.&lt;/p&gt;

&lt;p&gt;Here’s why,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When the data needs to be accessed by deeply nested components, you end up passing props through multiple layers of components that don’t even need the data themselves, a problem known as prop drilling.&lt;/li&gt;
&lt;li&gt;This makes your code harder to maintain, harder to read, and prone to bugs as the app grows.&lt;/li&gt;
&lt;li&gt;If multiple components in different parts of the app need the same data, you’d have to restructure your component tree just to share that data properly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not considered a good practice for large scale or scalable applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  The better solution?
&lt;/h3&gt;

&lt;p&gt;Use React's Context API combined with Hooks to create a global data store. This allows any component in your app to access or update shared state without passing props manually through every level of the component tree.&lt;/p&gt;

&lt;p&gt;In this article, I’ll show you a simple, beginner friendly example of how to,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetch user data from a REST API&lt;/li&gt;
&lt;li&gt;Store it in a Context&lt;/li&gt;
&lt;li&gt;Access it from any component using the useContext() hook&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end, you’ll see how this pattern improves your app’s structure and makes your code more maintainable and scalable.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Context API and React Hooks?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Context API&lt;/strong&gt; lets you create a global data store that can be accessed from any component without prop drilling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React Hooks&lt;/strong&gt; like &lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;useEffect&lt;/code&gt;, and &lt;code&gt;useContext&lt;/code&gt; allow functional components to manage state and side effects.&lt;/p&gt;

&lt;p&gt;Together, they make it easy to manage and share data globally in your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example Scenario
&lt;/h2&gt;

&lt;p&gt;We want to,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetch a user's profile from a REST API&lt;/li&gt;
&lt;li&gt;Share that data globally&lt;/li&gt;
&lt;li&gt;Access it inside a UserProfile component&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1.Create the Context
&lt;/h3&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%2F8mtyalkf19phtruahfek.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%2F8mtyalkf19phtruahfek.png" alt="code of userContext.js" width="800" height="1044"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What’s happening here?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Created a User interface for our user object.&lt;/li&gt;
&lt;li&gt;Created a UserContextType for the shape of context value.&lt;/li&gt;
&lt;li&gt;Created the context using createContext().&lt;/li&gt;
&lt;li&gt;Used useState to store user data and useEffect to fetch data.&lt;/li&gt;
&lt;li&gt;Provided the user data globally via UserContext.Provider.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2.Create a Global Providers Wrapper
&lt;/h3&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%2Fq4glc0gmrlmpcmugn5zg.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%2Fq4glc0gmrlmpcmugn5zg.png" alt="code of app/providers.tsx" width="800" height="683"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3.Wrap Your Application in layout.tsx
&lt;/h3&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%2Fh81oi7s94clfpe1ijser.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%2Fh81oi7s94clfpe1ijser.png" alt="app/layout.tsx code" width="800" height="821"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4.Access the Context in a Component
&lt;/h3&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%2Fp73jyrsq89dmrs2xmdeh.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%2Fp73jyrsq89dmrs2xmdeh.png" alt="components/UserProfile.tsx code" width="800" height="730"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What’s happening here?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Imported useContext to consume UserContext.&lt;/li&gt;
&lt;li&gt;Displayed a loading message while data fetches.&lt;/li&gt;
&lt;li&gt;Displayed user name and email once available.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Now, when your app loads,&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It fetches the user data once.&lt;/li&gt;
&lt;li&gt;Stores it in a global context.&lt;/li&gt;
&lt;li&gt;Any component can read it using useContext().&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;React's Context API combined with Hooks is a simple, powerful pattern for managing and sharing global state in Next.js 14+ apps especially when working with REST APIs.&lt;/p&gt;

&lt;p&gt;Instead of passing data manually via props, you create a global context and let any component access or update shared data efficiently.&lt;/p&gt;

&lt;p&gt;This TypeScript based implementation ensures type safety and scalable architecture, preparing your app for larger, more complex use cases.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>discuss</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Understanding the Difference Between .eq() and .match() in Supabase</title>
      <dc:creator>Dhamith Kumara</dc:creator>
      <pubDate>Sat, 24 May 2025 14:15:32 +0000</pubDate>
      <link>https://dev.to/bdhamithkumara/understanding-the-difference-between-eq-and-match-in-supabase-3m09</link>
      <guid>https://dev.to/bdhamithkumara/understanding-the-difference-between-eq-and-match-in-supabase-3m09</guid>
      <description>&lt;p&gt;Supabase is an open source backend as a service (BaaS) that provides developers with a powerful and easy to use interface for managing databases. Built on top of PostgreSQL, Supabase offers a real time database, authentication, and storage solutions, allowing developers to build applications quickly without managing backend infrastructure. In this article, we will explore two important methods for filtering data.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Supabase?
&lt;/h2&gt;

&lt;p&gt;Supabase aims to simplify the development process by providing a suite of tools that integrate seamlessly with PostgreSQL. It offers features such as,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-time subscriptions - Listen for changes in your database in real-time.&lt;/li&gt;
&lt;li&gt;Authentication - Built in user management and authentication.&lt;/li&gt;
&lt;li&gt;Storage - Manage files and media easily.&lt;/li&gt;
&lt;li&gt;APIs - Automatically generated RESTful APIs for your database tables.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The .eq() Method
&lt;/h2&gt;

&lt;p&gt;The .eq() method is used to filter records in a table where a specific column matches a given value. This method is particularly useful when you want to retrieve rows that meet a single condition.&lt;/p&gt;

&lt;h2&gt;
  
  
  Syntax
&lt;/h2&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%2Fswa51x3qsr0dt2qj1hvd.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%2Fswa51x3qsr0dt2qj1hvd.png" alt="The .eq() Method Syntax " width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;Suppose you have a users table and you want to find a user with the id of 1. You can use the .eq() method as follows&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%2Fx43e0jt183gf4fdg1bgp.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%2Fx43e0jt183gf4fdg1bgp.png" alt="The .eq() Method Example" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This query will return the user record where the id is equal to 1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Cases for .eq()
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Single Record Retrieval - When you need to fetch a specific record based on a unique identifier, such as an id.&lt;/li&gt;
&lt;li&gt;Filtering by Status - For example, retrieving all users with a specific status (e.g., active or inactive).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The .match() Method
&lt;/h2&gt;

&lt;p&gt;The .match() method allows you to filter records based on multiple conditions at once. It takes an object where the keys are the column names and the values are the values you want to match. This method is particularly useful for more complex queries where you need to filter by multiple fields.&lt;/p&gt;

&lt;h2&gt;
  
  
  Syntax
&lt;/h2&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%2Fmdpwhtjt3p5trazndcx2.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%2Fmdpwhtjt3p5trazndcx2.png" alt="The .match() Method Syntax" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;Continuing with the users table, if you want to find a user with both id of 1 and email of '&lt;a href="mailto:abc@abc.com"&gt;abc@abc.com&lt;/a&gt;', you can use the .match() method&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%2Fq8v1tljniddly6a650zz.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%2Fq8v1tljniddly6a650zz.png" alt="The .match() Method Example" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This query will return the user record that matches both conditions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Cases for .match()
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Complex Filtering - When you need to filter records based on multiple attributes, such as finding users by both role and status.&lt;/li&gt;
&lt;li&gt;Batch Queries - When you want to retrieve records that meet several criteria without chaining multiple .eq() calls.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Supabase provides powerful methods for querying data, and understanding how to use .eq() and .match() effectively can greatly enhance your ability to interact with your database. By leveraging these methods, you can build more efficient and complex queries, making your applications more robust and responsive.&lt;/p&gt;

&lt;p&gt;With the right practices and optimizations, you can ensure that your application performs well, even as your data grows. Whether you are building a small project or a large scale application, mastering these querying techniques will be invaluable.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Why the alt Attribute Matters?</title>
      <dc:creator>Dhamith Kumara</dc:creator>
      <pubDate>Thu, 15 May 2025 06:57:51 +0000</pubDate>
      <link>https://dev.to/bdhamithkumara/why-the-alt-attribute-matters-3gan</link>
      <guid>https://dev.to/bdhamithkumara/why-the-alt-attribute-matters-3gan</guid>
      <description>&lt;p&gt;Images are an essential part of the web. They inform, engage, and enhance the overall user experience. But what happens when an image fails to load, or when a user cannot see it? That’s where the humble alt attribute of the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag comes into play, serving as a vital link between visual content and universal accessibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the alt Attribute?
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;alt&lt;/code&gt; attribute in HTML provides alternative text for an image. This text is displayed if the image cannot load. More importantly, it is read aloud by screen readers, helping visually impaired users understand the content and context of images. &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%2Fvn2z0jlyrgxbmyc19xet.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%2Fvn2z0jlyrgxbmyc19xet.png" alt="sample of correct alt tag" width="800" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is the &lt;code&gt;alt&lt;/code&gt; Attribute Important?
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;alt&lt;/code&gt; attribute serves several important purposes,&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Accessibility for Screen Readers
&lt;/h3&gt;

&lt;p&gt;Visually impaired users rely on screen readers to navigate the web. The &lt;code&gt;alt&lt;/code&gt; text provides a textual description of images, giving these users critical context and meaning that would otherwise be lost.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Context When Images Fail to Load
&lt;/h3&gt;

&lt;p&gt;If a browser can’t load an image due to network issues, broken links, or other problems, the &lt;code&gt;alt&lt;/code&gt; text appears in its place. This helps users understand what information they are missing and maintains the continuity of the page content.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Improved Search Engine Optimization (SEO)
&lt;/h3&gt;

&lt;p&gt;Search engines can't "see" images the way humans do. The &lt;code&gt;alt&lt;/code&gt; attribute provides important context about the image, helping search engines understand your page content better. Well written &lt;code&gt;alt&lt;/code&gt; text can improve image search rankings and overall SEO performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Support for Text Based Browsers
&lt;/h3&gt;

&lt;p&gt;Though increasingly rare, some users still use text based browsers. The &lt;code&gt;alt&lt;/code&gt; text ensures these users access the information conveyed by images.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crafting Effective alt Text
&lt;/h2&gt;

&lt;p&gt;Writing good alt text is an art that balances clarity, brevity, and context. Follow these principles to write meaningful alt attributes,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Be Descriptive and Contextual - Describe the image and its purpose as if explaining it to someone who can't see it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep it Concise - Aim for a brief, one or two sentence description. Overly long alt text can burden screen reader users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use Relevant Keywords Naturally - If relevant, include keywords thoughtfully to benefit SEO, but avoid keyword stuffing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoid Redundant Phrases: Don’t use phrases like "image of" or "picture of" screen readers already announce images.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reflect the Image's Function - If the image functions as a link or button, describe its purpose or destination.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use Empty Alt for Decorative Images - For purely decorative images that add no content value, use an empty alt attribute alt="" to allow screen readers to skip them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use Real Text Instead of Text in Images - Whenever possible, avoid using images to display text. Use HTML text for better accessibility and SEO.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Good and Bad Examples
&lt;/h2&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%2F05kujo51rndacyoyd435.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%2F05kujo51rndacyoyd435.png" alt="alt first good example" width="800" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Good ✔ &lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's descriptive and specific.&lt;/li&gt;
&lt;li&gt;It tells both what the image is (company logo) and what it depicts (a stylized blue bird in flight).&lt;/li&gt;
&lt;li&gt;Helpful for screen readers and gives useful context.&lt;/li&gt;
&lt;/ul&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%2Fmk42bvwi7tpejmwp3bb0.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%2Fmk42bvwi7tpejmwp3bb0.png" alt="alt second good example" width="800" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Good ✔ &lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It’s clear, descriptive, and paints a specific image in the reader’s mind.&lt;/li&gt;
&lt;li&gt;Great for accessibility and good for SEO because it naturally mentions relevant, specific content without overdoing it.&lt;/li&gt;
&lt;/ul&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%2F4fudpg5t6dp73rby7ci1.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%2F4fudpg5t6dp73rby7ci1.png" alt="alt first bad example" width="772" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;bad ❌&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It’s too vague and doesn’t tell what the logo represents.&lt;/li&gt;
&lt;li&gt;Screen readers users would just hear “logo”, which is unhelpful.&lt;/li&gt;
&lt;/ul&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%2Fk4hlruvbh5gvf2nlg4dv.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%2Fk4hlruvbh5gvf2nlg4dv.png" alt="alt second bad example" width="800" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;bad ❌&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is a classic example of keyword stuffing.&lt;/li&gt;
&lt;li&gt;It's a list of keywords with no real sentence structure or meaning.&lt;/li&gt;
&lt;li&gt;Bad for accessibility (screen readers will read this awkwardly) and can harm SEO.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Alt Text Fixer Can Help You
&lt;/h2&gt;

&lt;p&gt;Managing alt attributes manually can be tedious, especially on larger projects. That’s why I created Alt Text Fixer, a lightweight and beginner friendly Visual Studio Code extension that helps you quickly find missing alt attributes and add or edit them directly in your editor.&lt;/p&gt;

&lt;p&gt;Key Features -&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scan your files for images missing alt attributes&lt;/li&gt;
&lt;li&gt;Quickly add or update alt text without leaving VS Code&lt;/li&gt;
&lt;li&gt;Improve your site's accessibility and SEO compliance effortlessly&lt;/li&gt;
&lt;li&gt;Lightweight and fast, perfect for developers of all skill levels&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=bdhamithkumara.alt-text-fixer" rel="noopener noreferrer"&gt;get it now &lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
