<?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: Jerry Satpathy</title>
    <description>The latest articles on DEV Community by Jerry Satpathy (@j3rry320).</description>
    <link>https://dev.to/j3rry320</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%2F238168%2F8c784c55-d9da-443c-9786-895342f95e95.jpeg</url>
      <title>DEV Community: Jerry Satpathy</title>
      <link>https://dev.to/j3rry320</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/j3rry320"/>
    <language>en</language>
    <item>
      <title>Government Websites Don't Have to Look Like They're Stuck in 2010</title>
      <dc:creator>Jerry Satpathy</dc:creator>
      <pubDate>Sun, 31 May 2026 12:56:22 +0000</pubDate>
      <link>https://dev.to/j3rry320/government-websites-dont-have-to-look-like-theyre-stuck-in-2010-n7n</link>
      <guid>https://dev.to/j3rry320/government-websites-dont-have-to-look-like-theyre-stuck-in-2010-n7n</guid>
      <description>&lt;p&gt;This afternoon, I took on a personal redesign challenge: reimagining a government tender portal using modern web design principles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The goal wasn't to criticise the existing platform. Government systems often prioritise functionality, compliance, and long-term stability. However, many public-facing portals still struggle with usability, discoverability, and visual clarity.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So I asked a simple question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What if a government procurement platform were designed with the same care as modern SaaS products?&lt;/strong&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%2Ftzgo1jb3uy2jtc730202.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%2Ftzgo1jb3uy2jtc730202.png" alt="The Current Platform" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Approach
&lt;/h2&gt;

&lt;p&gt;Instead of treating the portal like an administrative dashboard, I redesigned it as a discovery-first experience.&lt;/p&gt;

&lt;p&gt;The new interface focuses on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Clear visual hierarchy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Faster access to opportunities&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mobile-friendly navigation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modern search and filtering experiences&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Improved accessibility and readability&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Trust-building through transparency and data visualisation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And out came &lt;a href="https://codemedialabs.in/demo/tender-portal" rel="noopener noreferrer"&gt;this&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%2Ftz8718bwi89wqwhn90ld.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%2Ftz8718bwi89wqwhn90ld.png" alt="Our Redesign" width="419" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Changes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Reimagined Hero Section
&lt;/h3&gt;

&lt;p&gt;The homepage now focuses on helping users discover opportunities rather than overwhelming them with navigation and dense information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modern Analytics Dashboard
&lt;/h3&gt;

&lt;p&gt;Procurement activity, tender trends, and vendor participation are presented through clean data visualisations instead of traditional tables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Opportunity-Centric Design
&lt;/h3&gt;

&lt;p&gt;Featured tenders and procurement categories are showcased using modern card layouts that make important information easier to scan and understand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consistent Design System
&lt;/h3&gt;

&lt;p&gt;Every section follows the same visual language, spacing system, typography scale, and component patterns to create a more cohesive experience.&lt;/p&gt;

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

&lt;p&gt;The redesign was built using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Next.js&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TypeScript&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tailwind CSS&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Recharts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lucide Icons&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Digital public infrastructure impacts millions of people.&lt;/p&gt;

&lt;p&gt;When government websites are easier to use, citizens spend less time searching for information, vendors can participate more easily in procurement processes, and organisations benefit from increased transparency and engagement.&lt;/p&gt;

&lt;p&gt;Modern UX isn't just about aesthetics. It's about reducing friction.&lt;/p&gt;

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

&lt;p&gt;This project is a concept redesign exploring how public-sector digital experiences can evolve using modern design and development practices.&lt;/p&gt;

&lt;p&gt;Government websites don't need to look flashy.&lt;/p&gt;

&lt;p&gt;They need to be clear, accessible, trustworthy, and pleasant to use.&lt;/p&gt;

&lt;p&gt;And with today's tools and design systems, that's more achievable than ever.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href="https://codemedialabs.in/demo/tender-portal" rel="noopener noreferrer"&gt;demo!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And as always, Happy Coding &amp;amp; Designing!&lt;/p&gt;




&lt;p&gt;Designed and developed as a concept by Code Media Labs.&lt;/p&gt;

</description>
      <category>design</category>
      <category>ui</category>
      <category>webdev</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>I Built an AI-Powered Interview Simulator That Runs Entirely in Your Terminal</title>
      <dc:creator>Jerry Satpathy</dc:creator>
      <pubDate>Fri, 29 May 2026 15:59:55 +0000</pubDate>
      <link>https://dev.to/j3rry320/i-built-an-ai-powered-interview-simulator-that-runs-entirely-in-your-terminal-nmp</link>
      <guid>https://dev.to/j3rry320/i-built-an-ai-powered-interview-simulator-that-runs-entirely-in-your-terminal-nmp</guid>
      <description>&lt;p&gt;&lt;strong&gt;Interview prep is mostly passive.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You read through question lists, watch videos, or practice with a friend if you can find one. None of it feels particularly real.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://www.npmjs.com/package/interview-coach" rel="noopener noreferrer"&gt;&lt;strong&gt;Interview Coach&lt;/strong&gt;&lt;/a&gt;, a CLI tool that runs mock interviews, scores your answers, and gives you a breakdown of what you did well and where you fell short.&lt;/p&gt;

&lt;h2&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%2Fj0u5l432hm9gy1oceid8.png" alt=" " width="800" height="800"&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;interview-coach start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pick a role, an experience level, and how many questions you want. The interview starts immediately.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;★ Question 1/5

Category: React
Difficulty: Medium

How would you optimise a React application experiencing unnecessary re-renders?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After each answer, you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A score&lt;/li&gt;
&lt;li&gt;A verdict&lt;/li&gt;
&lt;li&gt;Specific feedback&lt;/li&gt;
&lt;li&gt;What a strong answer would have looked like&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the end, a full session report is generated.&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%2Fwnnw6h814pzs2hdep5jv.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%2Fwnnw6h814pzs2hdep5jv.png" alt=" " width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  It's not just for developers
&lt;/h2&gt;

&lt;p&gt;The questions adapt to the role you choose. A few examples:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content Writer&lt;/strong&gt; — &lt;em&gt;How would you rewrite a technical article for a non-technical audience?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sales Executive&lt;/strong&gt; — &lt;em&gt;A prospect says your product is too expensive. How would you respond?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Teacher&lt;/strong&gt; — &lt;em&gt;How would you explain a difficult concept to students with different learning styles?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Same tool, any profession.&lt;/p&gt;




&lt;h2&gt;
  
  
  Under the hood
&lt;/h2&gt;

&lt;p&gt;The stack is intentionally small: Node.js, Commander, Inquirer, Groq, Zod, Chalk, Ora, Boxen, Webpack.&lt;/p&gt;

&lt;p&gt;Sessions are saved locally, so you can review past reports and track how you're improving over time. Nothing leaves your machine except the requests to generate questions and evaluate answers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; interview-coach
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx interview-coach
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;npm: &lt;a href="https://www.npmjs.com/package/interview-coach" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/interview-coach&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/J3rry320/interview-coach" rel="noopener noreferrer"&gt;https://github.com/J3rry320/interview-coach&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feedback, bug reports, and contributions are welcome.&lt;br&gt;
And as always, happy coding!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>node</category>
      <category>npm</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I Reimagined the Cuttack Municipal Corporation Website with Next.js, Tailwind &amp; Recharts</title>
      <dc:creator>Jerry Satpathy</dc:creator>
      <pubDate>Thu, 28 May 2026 07:58:45 +0000</pubDate>
      <link>https://dev.to/j3rry320/i-reimagined-the-cuttack-municipal-corporation-website-with-nextjs-tailwind-recharts-gng</link>
      <guid>https://dev.to/j3rry320/i-reimagined-the-cuttack-municipal-corporation-website-with-nextjs-tailwind-recharts-gng</guid>
      <description>&lt;h2&gt;
  
  
  Redesigning a Municipal Website: CMC Cuttack
&lt;/h2&gt;

&lt;p&gt;Government websites are some of the most important digital products people use. People rely on them for taxes, certificates, complaints, licenses, public notices, and emergency information.&lt;/p&gt;

&lt;p&gt;But many municipal portals across India still feel stuck in the early 2010s, with cluttered layouts, poor mobile usability, overwhelming menus, low accessibility, and information overload.&lt;/p&gt;

&lt;p&gt;So I decided to redesign one.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Existing Website
&lt;/h2&gt;

&lt;p&gt;I picked the official Cuttack Municipal Corporation website: &lt;a href="https://cmccuttack.odisha.gov.in/" rel="noopener noreferrer"&gt;cmccuttack.odisha.gov.in&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%2F4v0g6mefyuzewmd5m1yv.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%2F4v0g6mefyuzewmd5m1yv.png" alt="Existing Website" width="800" height="720"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CMC already offers several important citizen services, including property tax, trade license, grievance redressal, water and sewerage, tenders and notices. The functionality exists. But the overall experience still feels information-heavy, visually dense, and inconsistent on mobile, especially for non-technical users.&lt;/p&gt;

&lt;p&gt;And honestly, this is not just a Cuttack problem. Most government websites across India still prioritise listing information over designing usable digital experiences.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Goal
&lt;/h2&gt;

&lt;p&gt;The idea was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What if a municipal website felt more like a civic operating system instead of a static government portal?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I wanted it to feel alive, responsive, transparent, and approachable, with modern layouts, a citizen-first hierarchy, and real-time data visibility. Instead of treating the site like a document archive, I wanted it to feel like a living platform.&lt;/p&gt;

&lt;p&gt;You can explore the live demo here: &lt;a href="https://www.codemedialabs.in/demo/cmc" rel="noopener noreferrer"&gt;codemedialabs.in/demo/cmc&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%2Fuiih8tcmihk50u9p35vn.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%2Fuiih8tcmihk50u9p35vn.png" alt="Our Redesign" width="800" height="820"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;p&gt;The concept is built with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js&lt;/strong&gt; — for the app framework and routing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind CSS&lt;/strong&gt; — for the utility-first styling system&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lucide React&lt;/strong&gt; — for the icon set throughout the UI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recharts&lt;/strong&gt; — for all the data visualisation components&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal was to keep the frontend lightweight, scalable, and production-ready, with a heavy focus on spacing systems, typography hierarchy, responsive behaviour, and accessibility-friendly layouts.&lt;/p&gt;




&lt;h2&gt;
  
  
  Design Direction
&lt;/h2&gt;

&lt;p&gt;One thing I was careful about: not making this feel like a crypto dashboard, an admin panel template, or a startup SaaS clone. Government platforms need a different visual language. They should feel trustworthy, calm, readable, and authoritative.&lt;/p&gt;

&lt;p&gt;So the direction became: &lt;strong&gt;Apple-inspired minimalism + smart city dashboards + civic accessibility.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The UI uses large typography, clean spacing, modular cards, muted gradients, and structured information blocks — without becoming visually overwhelming.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Navbar
&lt;/h3&gt;

&lt;p&gt;The navigation is sticky with a clean white backdrop and subtle blur. On desktop, it shows links for Services, Ward Info, Tenders, Dashboard, and About, alongside Sign In and Pay Online CTAs. On mobile, it collapses into a smooth CSS-animated drawer that locks scroll and closes on outside click.&lt;/p&gt;




&lt;h3&gt;
  
  
  Hero Section
&lt;/h3&gt;

&lt;p&gt;The original CMC portal immediately overwhelms users with dense navigation and competing content. The redesigned hero focuses on three things:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A search bar&lt;/strong&gt; — the primary action. Large, prominent, with a blue search button, and popular service tags below it (Property Tax, Trade License, Water Bill, Building Approval), so users don't have to think.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Quick Actions card&lt;/strong&gt; — a dark blue panel on the right with six instant-access buttons: Property Tax, Register Complaint, Water Bill, Trade License, Track Application, and Certificates. Each has an icon and lifts slightly on hover.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A stats strip&lt;/strong&gt; — anchored below the hero fold, spanning four key numbers: 2.67L+ Citizens Served, 12,458 Complaints Resolved, 95% Water Coverage, and 312 MT Waste Collected Today. Small but impactful — it immediately communicates scale and activity.&lt;/p&gt;




&lt;h3&gt;
  
  
  Citizen Services
&lt;/h3&gt;

&lt;p&gt;Four service cards arranged in a responsive grid:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Property Tax&lt;/strong&gt; — pay online quickly and securely&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grievance Redressal&lt;/strong&gt; — register and track civic complaints with real-time updates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Water &amp;amp; Sewerage&lt;/strong&gt; — apply for new connections and manage utility bills&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Building Approval&lt;/strong&gt; — submit and track building plan approval requests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each card has a colour-coded icon, a description, and an "Explore Service" link that animates on hover. Clean, scannable, no clutter.&lt;/p&gt;




&lt;h3&gt;
  
  
  Dashboard Preview
&lt;/h3&gt;

&lt;p&gt;This section does two things in a split layout:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Civic Performance chart&lt;/strong&gt; — a Recharts area chart showing service efficiency across six dimensions: Sanitation, Water, Transport, Emergency, Waste Management, and Citizen Services. It has a "LIVE" badge and a styled tooltip with a glossy card. The gradient fill under the line gives it a premium feel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Notices &amp;amp; Updates panel&lt;/strong&gt; — a dark blue card with the three most recent notices, each tagged by type (NOTICE, TENDER, NEWS) with colour-coded badges and dates. A "View All" link sits at the top.&lt;/p&gt;




&lt;h3&gt;
  
  
  Know Your Ward + City Highlight
&lt;/h3&gt;

&lt;p&gt;A two-column section with two very different jobs:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Know Your Ward&lt;/strong&gt; — a dark blue card with a search input for ward number or property ID. Below it are four quick-access buttons: Ward Councillor, Garbage Schedule, Water Supply, and Flood Alerts. This is the hyperlocal civic layer that most government sites completely miss — especially relevant for Cuttack during monsoon seasons and waterlogging situations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cuttack — The Silver City&lt;/strong&gt; — an immersive photo panel with a gradient overlay, showcasing the city's identity. The copy leans into Cuttack's 1000-year heritage, silver filigree craftsmanship, and the Mahanadi river. Four identity tags: Millennium City, Silver Filigree, Mahanadi River, Smart City. Two CTAs: Explore Cuttack and City Dashboard.&lt;/p&gt;




&lt;h3&gt;
  
  
  Governance Intelligence
&lt;/h3&gt;

&lt;p&gt;A full section built around making civic operations visible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Four KPI cards at the top:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avg Response Time: 2.4 hrs (down 18%)&lt;/li&gt;
&lt;li&gt;Ward Satisfaction: 91% (up 6%)&lt;/li&gt;
&lt;li&gt;Digital Applications: 18.2K (up 22%)&lt;/li&gt;
&lt;li&gt;Infrastructure Health: 88% (up 9%)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ward Analytics&lt;/strong&gt; — a Recharts RadarChart comparing five wards (W-12, W-18, W-24, W-31, W-42) across three dimensions: Sanitation, Water supply, and Grievance resolution. It gives an immediate sense of which wards are performing and which need attention.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Infrastructure Monitoring&lt;/strong&gt; — a dark card with five animated progress bars showing active status for Street Lights (94%), Water Pumps (88%), Drain Sensors (72%), Traffic Signals (91%), and CCTV Network (86%). Below that, three stat blocks: 128 Flood Sensors, 42 Air Quality Nodes, 67 Smart Signals.&lt;/p&gt;




&lt;h3&gt;
  
  
  Live City Monitoring
&lt;/h3&gt;

&lt;p&gt;This was the most technically interesting part of the project.&lt;/p&gt;

&lt;p&gt;A live SVG map of Cuttack with ten ward nodes plotted across a grid background with a stylised Mahanadi river path. Each ward is colour-coded by risk level — green for Normal, amber for Watch, red for Critical — with a halo effect around each node. Hovering a ward shows a tooltip with its drainage percentage, traffic load, and flood risk.&lt;/p&gt;

&lt;p&gt;Above the map, five metric cards update every 2.2 seconds with randomised values simulating live telemetry: Drainage Health, Flood Risk, Field Teams, Traffic Load, and New Complaints. The numbers fluctuate in realistic ranges, so the dashboard feels genuinely alive.&lt;/p&gt;

&lt;p&gt;Below the map, ten ward cards display the static data for each area — Buxi Bazaar, Choudhury Bazaar, Ranihat, College Square, Mangalabag, CDA Sector 6, Badambadi, Jobra, Cantonment, and Nimpur — each with a pulsing dot in its risk colour.&lt;/p&gt;




&lt;h3&gt;
  
  
  Smart Civic Analytics
&lt;/h3&gt;

&lt;p&gt;Three charts that transform raw data into transparency:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Grievance Resolution&lt;/strong&gt; — a Recharts BarChart comparing resolved vs. pending complaints from January to May. Dark blue bars for resolved, light blue for pending. The trend is obvious at a glance: resolve rates are climbing, backlogs are shrinking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Budget Allocation&lt;/strong&gt; — a doughnut PieChart showing FY 2025–26 sectoral spending: Roads (35%), Water (25%), Sanitation (20%), Parks (10%), Health (10%). Simple and honest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Water Supply Stability&lt;/strong&gt; — a full-width dark blue LineChart spanning the whole week (Monday to Sunday), showing daily uptime percentages across all wards. Weekly average: 95.6%, shown in a floating stat card above the chart.&lt;/p&gt;




&lt;h3&gt;
  
  
  Leadership
&lt;/h3&gt;

&lt;p&gt;Two profile cards for the Mayor (Shri Subhash Chandra Singh) and the Commissioner (Ms Kirandeep Kaur Sahota, IAS). Each has a photo, role badge, a short bio, and two stat blocks — Active Projects and Civic Drives for the Mayor; Smart Projects and Digital Services for the Commissioner. The cards have a subtle glow that expands on hover.&lt;/p&gt;




&lt;h3&gt;
  
  
  Footer
&lt;/h3&gt;

&lt;p&gt;A full dark footer (&lt;code&gt;#07152d&lt;/code&gt;) with a top CTA bar, a four-column grid (brand + stats, Quick Links, Important Links, Contact), and a bottom bar with copyright and legal links. The contact section shows the CMC address on Link Road, Cuttack, the 1800 345 6767 helpline, and &lt;a href="mailto:cmc@cuttack.gov.in"&gt;cmc@cuttack.gov.in&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Design Challenges
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Designing for Trust
&lt;/h3&gt;

&lt;p&gt;This was the most interesting constraint. Civic platforms cannot feel gimmicky, startup-ish, or trend-chasing. The UI needs to balance authority, simplicity, and professionalism while still feeling modern. That balance is much harder than designing a typical SaaS dashboard — and it shaped almost every decision, from the navy palette to the conservative use of animation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Balancing Information Density
&lt;/h3&gt;

&lt;p&gt;Government websites contain large amounts of information by nature. The challenge is not removing it — it's structuring it properly: prioritising actions, improving discoverability, reducing cognitive load through spacing, grouping, and visual rhythm.&lt;/p&gt;




&lt;h2&gt;
  
  
  What This Tells Us
&lt;/h2&gt;

&lt;p&gt;Government websites are public infrastructure. Bad UX in civic systems creates confusion, accessibility barriers, lower digital adoption, and reduced trust. When millions of citizens interact with a system, even small usability improvements matter enormously.&lt;/p&gt;

&lt;p&gt;This redesign is an exploration of what that future could look like, a municipal platform that feels transparent, fast, mobile-friendly, and genuinely citizen-first.&lt;/p&gt;

&lt;p&gt;Especially as more public services move online across India, this kind of design thinking deserves to be part of the conversation.&lt;/p&gt;

&lt;p&gt;If you're working on a government platform, civic tech product, or any digital experience that needs to go beyond the template, we'd love to help build it. At Code Media Labs, we design and develop production-ready systems that are fast, accessible, and actually enjoyable to use. Whether you're starting from scratch or modernising something long overdue for a rethink, reach out at &lt;a href="https://codemedialabs.in/contact" rel="noopener noreferrer"&gt;codemedialabs.in&lt;/a&gt;and let's build something worth using.&lt;/p&gt;

&lt;p&gt;And as always, happy coding.&lt;/p&gt;




&lt;p&gt;Built by &lt;a href="https://codemedialabs.in" rel="noopener noreferrer"&gt;Code Media Labs&lt;/a&gt;. Live demo: &lt;a href="https://www.codemedialabs.in/demo/cmc" rel="noopener noreferrer"&gt;codemedialabs.in/demo/cmc&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>uidesign</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Announcing markdown-parser-react v3.0.0: A Complete Architectural Overhaul</title>
      <dc:creator>Jerry Satpathy</dc:creator>
      <pubDate>Sun, 12 Apr 2026 07:57:51 +0000</pubDate>
      <link>https://dev.to/j3rry320/announcing-markdown-parser-react-v300-a-complete-architectural-overhaul-p2o</link>
      <guid>https://dev.to/j3rry320/announcing-markdown-parser-react-v300-a-complete-architectural-overhaul-p2o</guid>
      <description>&lt;p&gt;Markdown is the backbone of the modern web—from documentation to personal blogs. But for too long, React developers have had to choose between "lightweight but insecure" or "robust but heavy."&lt;/p&gt;

&lt;p&gt;Today, I’m thrilled to announce the launch of markdown-parser-react v3.0.0. This is a ground-up rewrite designed for the security-conscious, performance-driven developer.&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%2Fcw11i0fgw5glu14v8vuk.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%2Fcw11i0fgw5glu14v8vuk.png" alt="Markdown-parser-react v3.0.0" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why an Overhaul?
&lt;/h2&gt;

&lt;p&gt;The Core Reason was the Move to Token-Based Rendering&lt;br&gt;
In previous versions, we relied on standard HTML rendering. In v3, we’ve moved entirely away from dangerouslySetInnerHTML.&lt;/p&gt;

&lt;p&gt;The core of the library is now a &lt;strong&gt;Token-based React Renderer&lt;/strong&gt;. Instead of generating a raw HTML string, we parse Markdown into an AST (Abstract Syntax Tree) and convert those tokens directly into React nodes using React.createElement.&lt;/p&gt;
&lt;h2&gt;
  
  
  What does this mean for you?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Security by Design&lt;/strong&gt;: It is inherently protected against most XSS attacks because we aren't injecting raw strings into the DOM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;: It integrates perfectly with the React Lifecycle and Virtual DOM, ensuring smoother updates and flawless hydration in SSR environments like Next.js.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The "Everything is a Component" Philosophy&lt;/strong&gt;: Because every part of your markdown is now a React node, you can treat it like any other part of your app.&lt;/p&gt;
&lt;h2&gt;
  
  
  What’s New in v3?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Advanced Component Overrides (The Killer Feature)&lt;/strong&gt;&lt;br&gt;
This is where v3 truly shines. You can now swap any standard Markdown element for a custom React component.&lt;/p&gt;

&lt;p&gt;Want to replace a standard &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag with&lt;code&gt;next/link&lt;/code&gt; for client-side navigation? Or maybe turn &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; tags into beautifully styled Shadcn/UI headers? Now you can:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Markdown&lt;/span&gt; 
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
  &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CustomHeader&lt;/span&gt; &lt;span class="na"&gt;level&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;CustomHeader&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
      &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;InternalLink&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt;
      &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;language&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MySyntaxHighlighter&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MySyntaxHighlighter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. GitHub-Style Alerts &amp;amp; Native Footnotes&lt;/strong&gt;&lt;br&gt;
We’ve added native support for blockquote callouts ([!NOTE], [!TIP], etc.) and common markdown footnotes ([^1]). This makes the library perfect for academic writing, technical docs, or citation-heavy blogs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Advanced Math (TeX/LaTeX)&lt;/strong&gt;&lt;br&gt;
Math is no longer an afterthought. With support for inline ($) and block ($$) equations, you can use the onRenderMath hook to integrate engines like KaTeX or MathJax effortlessly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Semantic DX (Developer Experience)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WCAG Compliant&lt;/strong&gt;: New asArticle, id, and aria props ensure your rendered content is accessible. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strictly Typed&lt;/strong&gt;: Full TypeScript support for a better IDE experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure Defaults&lt;/strong&gt;: sanitizeHtml is now enabled by default.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  The Vision: Code Media Labs
&lt;/h2&gt;

&lt;p&gt;With v3, markdown-parser-react officially transitions under the &lt;a href="https://codemedialabs.in" rel="noopener noreferrer"&gt;Code Media Labs&lt;/a&gt; branding. Our mission is to build lightweight, high-performance tools that solve real-world problems for the modern web and open-source those tools for everyone to use.&lt;/p&gt;

&lt;p&gt;This package is a core component of the ecosystem we are building. By making markdown rendering safe and extensible, we’re setting the stage for more complex systems.&lt;/p&gt;

&lt;p&gt;What's Next?&lt;br&gt;
Our focus at &lt;a href="https://codemedialabs.in" rel="noopener noreferrer"&gt;Code Media Labs&lt;/a&gt; is currently split between infrastructure and intelligence:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://synapse.codemedialabs.in" rel="noopener noreferrer"&gt;Synapse&lt;/a&gt;: Our upcoming "Intelligent Factory Operating System." We are applying the same high-performance standards used in this library to build a robust ERP platform for industrial environments.&lt;/p&gt;

&lt;p&gt;Mira: Our internal intelligence engine.** Mira isn't just about sentiment analysis; it's a multimodal suite**. It combines high-speed demographic analytics with a custom TTS (Text-to-Speech) system built on top of Piper. Whether it's parsing public sentiment or giving that data a voice, Mira is designed for speed and privacy.&lt;/p&gt;

&lt;p&gt;Get Started&lt;br&gt;
If you’re looking for a markdown solution that doesn’t compromise on security or React-native features, give v3 a spin.&lt;/p&gt;

&lt;p&gt;Install it now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;markdown-parser-react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out the docs:&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/markdown-parser-react" rel="noopener noreferrer"&gt;Markdown-Parser-React&lt;/a&gt;&lt;br&gt;
I’d love to hear your feedback! Let’s build a better, safer web together. And as always, Happy Coding&lt;/p&gt;

&lt;p&gt;Follow me for more updates on Next.js, TypeScript, and our journey at &lt;a href="https://codemedialabs.in" rel="noopener noreferrer"&gt;Code Media Labs&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>opensource</category>
      <category>npm</category>
    </item>
    <item>
      <title>Your React App Breaks When the Internet Drops. Here’s a Better Way.</title>
      <dc:creator>Jerry Satpathy</dc:creator>
      <pubDate>Sat, 28 Feb 2026 10:58:49 +0000</pubDate>
      <link>https://dev.to/j3rry320/your-react-app-breaks-when-the-internet-drops-heres-a-better-way-1l7h</link>
      <guid>https://dev.to/j3rry320/your-react-app-breaks-when-the-internet-drops-heres-a-better-way-1l7h</guid>
      <description>&lt;p&gt;&lt;em&gt;Internet connectivity is outside a developer’s control.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;User experience is not.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When a connection drops, most applications either freeze silently, fail API calls without feedback, or leave users staring at broken UI states. &lt;strong&gt;The result is confusion, repeated actions, and unnecessary frustration.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React Network Notifier&lt;/strong&gt; exists to solve this problem cleanly. It detects network changes, surfaces clear offline messaging, and manages reconnect transitions without adding dependencies or boilerplate to your application.&lt;/p&gt;

&lt;p&gt;Version 2.0.0 is a complete rewrite focused on performance, flexibility, and modern React compatibility.&lt;/p&gt;
&lt;h2&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%2Fb9grpvz3ox46mrhowczu.png" alt="react-network-notifier" width="800" height="800"&gt;
&lt;/h2&gt;
&lt;h2&gt;
  
  
  What It Does
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;react-network-notifier&lt;/code&gt; is a zero-dependency React component that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Detects network disconnection&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Displays configurable offline states&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Handles reconnect events with smooth transitions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Works with React and Next.js&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supports Server-Side Rendering (SSR)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  What’s New in v2.0.0
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Rewritten Build System (Microbundle → Tsup)
&lt;/h3&gt;

&lt;p&gt;The package was rebuilt using Tsup.&lt;/p&gt;

&lt;p&gt;Results:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Smaller bundle&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Faster build pipeline&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Final bundle size under 10KB (minified)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  2. Multiple Layout Variants
&lt;/h3&gt;

&lt;p&gt;Three visual modes are now supported:&lt;/p&gt;

&lt;p&gt;variant="toast"&lt;br&gt;&lt;br&gt;
variant="banner"&lt;br&gt;&lt;br&gt;
variant="fullscreen"&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;toast&lt;/code&gt;: small floating notification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;banner&lt;/code&gt;: horizontal alert&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;fullscreen&lt;/code&gt;: immersive offline state (default)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes the component usable across dashboards, SaaS products, and internal tools.&lt;/p&gt;


&lt;h3&gt;
  
  
  3. Native Dark Mode Support
&lt;/h3&gt;

&lt;p&gt;Theme configuration:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;theme="light"  |  "dark"  |  "system"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;When set to &lt;code&gt;"system"&lt;/code&gt;, the component respects the user’s OS preference automatically.&lt;/p&gt;


&lt;h3&gt;
  
  
  4. Reconnect State Handling
&lt;/h3&gt;

&lt;p&gt;When connectivity returns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A success message is shown&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The component transitions out smoothly&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reconnect messages are fully customizable.&lt;/p&gt;


&lt;h3&gt;
  
  
  5. ASCII or SVG Icons
&lt;/h3&gt;

&lt;p&gt;Two icon modes are supported:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iconType="ascii"  
iconType="svg"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This allows the component to fit both retro developer tools and modern UI systems.&lt;/p&gt;


&lt;h3&gt;
  
  
  6. CSS Modules Instead of Inline Styles
&lt;/h3&gt;

&lt;p&gt;Version 2 removes heavy inline style objects and uses injected CSS modules instead.&lt;/p&gt;

&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Reduced runtime overhead&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cleaner rendering&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Improved performance consistency&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;react-network-notifier  
&lt;span class="c"&gt;# or  &lt;/span&gt;
yarn add react-network-notifier
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Basic Usage
&lt;/h2&gt;

&lt;p&gt;Add it to your root layout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt;  &lt;span class="nx"&gt;NetworkNotifier&lt;/span&gt;  &lt;span class="k"&gt;from&lt;/span&gt;  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-network-notifier&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="kd"&gt;function&lt;/span&gt;  &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
  &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;  
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;NetworkNotifier&lt;/span&gt;  &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;  
 &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Your application */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt;  &lt;span class="k"&gt;default&lt;/span&gt;  &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No configuration required.&lt;/p&gt;




&lt;h2&gt;
  
  
  Custom Configuration Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt;  &lt;span class="nx"&gt;NetworkNotifier&lt;/span&gt;  &lt;span class="k"&gt;from&lt;/span&gt;  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-network-notifier&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="kd"&gt;const&lt;/span&gt;  &lt;span class="nx"&gt;customMessages&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;  
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;It looks like your router took a coffee break.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Offline mode activated.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
&lt;span class="p"&gt;];&lt;/span&gt;  

&lt;span class="kd"&gt;const&lt;/span&gt;  &lt;span class="nx"&gt;reconnectMessages&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;  
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Connection restored.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
&lt;span class="p"&gt;];&lt;/span&gt;  

&lt;span class="kd"&gt;function&lt;/span&gt;  &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;NetworkNotifier&lt;/span&gt;  
  &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;customMessages&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="nx"&gt;reconnectMessages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;reconnectMessages&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;toast&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;  
  &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;  
  &lt;span class="nx"&gt;iconType&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;  
  &lt;span class="nx"&gt;closable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="sr"&gt;/&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Configuration Props
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Prop&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;messages&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Array of strings displayed when the connection is lost.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;reconnectMessages&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Array of strings displayed when the connection is restored.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;images&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Array of ASCII art strings shown during offline states.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;styles&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;React.CSSProperties&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Inline styles to override or extend default component CSS.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;variant&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`"toast" \&lt;/td&gt;
&lt;td&gt;"banner" \&lt;/td&gt;
&lt;td&gt;"fullscreen"`&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;iconType&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`"ascii" \&lt;/td&gt;
&lt;td&gt;"svg"`&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"ascii"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;theme&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`"light" \&lt;/td&gt;
&lt;td&gt;"dark" \&lt;/td&gt;
&lt;td&gt;"system"`&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;closable&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;If &lt;code&gt;true&lt;/code&gt;, allows users to manually dismiss the notification.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Technical Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Zero dependencies&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under 10KB minified&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TypeScript-first&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SSR-safe&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tree-shakeable&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No runtime setup required&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;NPM:&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/react-network-notifier" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/react-network-notifier&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitHub:&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/J3rry320/react-network-notifier" rel="noopener noreferrer"&gt;https://github.com/J3rry320/react-network-notifier&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Offline handling is often treated as an edge case. In reality, it is a core UX scenario.&lt;/p&gt;

&lt;p&gt;React Network Notifier v2.0 is designed to integrate into modern React systems with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Minimal footprint&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No dependencies&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SSR safety&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configurable presentation&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you care about resilient UI architecture, this is a small but meaningful addition to your stack.&lt;/p&gt;

&lt;p&gt;Contributions and feedback are welcome.&lt;br&gt;
And as always Happy Coding! 🧑🏻‍💻&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Making Your Website Talk (Without Scaring Your Users)</title>
      <dc:creator>Jerry Satpathy</dc:creator>
      <pubDate>Fri, 06 Feb 2026 07:30:17 +0000</pubDate>
      <link>https://dev.to/j3rry320/making-your-website-talk-without-scaring-your-users-3299</link>
      <guid>https://dev.to/j3rry320/making-your-website-talk-without-scaring-your-users-3299</guid>
      <description>&lt;p&gt;Let’s be honest: most websites are too quiet. We spend our lives staring at glowing rectangles, reading text like it’s 1995. But your browser has a hidden superpower called the &lt;strong&gt;Web Speech API&lt;/strong&gt;. It can talk. And no, I don't mean those weird auto-playing video ads from 2008.&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%2Fwi2t282b2i5cz1auy3g3.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%2Fwi2t282b2i5cz1auy3g3.jpg" alt="Building a TTS Weather App" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today, we’re building a Weather Dashboard that doesn’t just show you the temperature—it summarises the vibes and reads them to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;React.js&lt;/strong&gt;: Because we like components and state management that makes sense.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Web Speech API&lt;/strong&gt;: Specifically &lt;code&gt;window.speechSynthesis&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;OpenWeatherMap API&lt;/strong&gt;: For the data (or any weather API of your choice).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. The "Brains": Fetching &amp;amp; Summarising
&lt;/h2&gt;

&lt;p&gt;First, we need something worth saying. A raw JSON response saying &lt;code&gt;{"temp": 273.15}&lt;/code&gt; is great for machines, but humans prefer "It's freezing, stay inside."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchWeatherSummary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://api.openweathermap.org/data/2.5/weather?q=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;appid=YOUR_API_KEY&amp;amp;units=metric`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// A simple summarizer (You could pipe this to an LLM for more "flavour")&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`Currently in &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, it's &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; degrees with &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;weather&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;. My professional advice? &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Wear a hat.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Grab a jacket.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. The "Voice": Meet SpeechSynthesis
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;window.speechSynthesis&lt;/code&gt; controller is the boss. It manages the queue of "utterances" (the things you want to say).&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;useSpeech&lt;/code&gt; Hook
&lt;/h3&gt;

&lt;p&gt;Don't clutter your UI logic. Let’s wrap the speech engine in a clean React hook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useSpeech&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;voices&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setVoices&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SpeechSynthesisVoice&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateVoices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setVoices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speechSynthesis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getVoices&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speechSynthesis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onvoiceschanged&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;updateVoices&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;updateVoices&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;speak&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;voiceName&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pitch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Cancel any ongoing chatter&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speechSynthesis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;utterance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SpeechSynthesisUtterance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Find the voice or default to the first one&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;voiceName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;voice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;voices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;voiceName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// 0.1 to 10&lt;/span&gt;
    &lt;span class="nx"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pitch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pitch&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 0 to 2&lt;/span&gt;

    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speechSynthesis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;speak&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;utterance&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;speak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;voices&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;pause&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speechSynthesis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pause&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="na"&gt;resume&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speechSynthesis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resume&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. The Dashboard Component
&lt;/h2&gt;

&lt;p&gt;Now, let’s glue it together. We’ll create a button that fetches the data and then reads it out loud.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useSpeech&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./hooks/useSpeech&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;WeatherDashboard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setSummary&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;speak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;voices&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSpeech&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleWeatherUpdate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchWeatherSummary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;London&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setSummary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;speak&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;voices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;p-8 max-w-md mx-auto bg-white rounded-xl shadow-md&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text-2xl font-bold&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Weather&lt;/span&gt; &lt;span class="nx"&gt;Talker&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; 
        &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleWeatherUpdate&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mt-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;Get&lt;/span&gt; &lt;span class="nx"&gt;Audio&lt;/span&gt; &lt;span class="nx"&gt;Summary&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mt-4 italic text-gray-600&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{summary}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  Pro-Tips for the Speech API
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Voices are Lazy&lt;/strong&gt;: Voices don't always load immediately. That &lt;code&gt;onvoiceschanged&lt;/code&gt; event in our hook is crucial; otherwise, your &lt;code&gt;voices&lt;/code&gt; array will be empty on the first render.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;User Activation&lt;/strong&gt;: Browsers hate noise. You cannot trigger &lt;code&gt;speak()&lt;/code&gt; on page load. It &lt;em&gt;must&lt;/em&gt; be inside a user-triggered event (like a click).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The "Vocalize" Shortcut&lt;/strong&gt;: If you want to skip the boilerplate, there is a handy NPM package called &lt;a href="https://www.npmjs.com/package/vocalize.ts" rel="noopener noreferrer"&gt;vocalize.ts&lt;/a&gt;. It’s a TypeScript-first wrapper for this exact API. Full disclosure: it’s currently in a bit of a dormant state, but the core logic is solid, and an update is coming soon to modernise the internals.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why bother?
&lt;/h2&gt;

&lt;p&gt;Accessibility is the obvious answer. Screen readers are great, but sometimes a specific "Read this for me" feature is exactly what a user needs when they're multitasking or vision-impaired.&lt;/p&gt;

&lt;p&gt;Plus, it's just fun to make your computer talk back to you. Just don't give it a sarcastic personality unless you're prepared for the consequences.&lt;/p&gt;

&lt;p&gt;And as always &lt;strong&gt;Happy coding!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The Day My Linux Server Started Distributing Windows Malware</title>
      <dc:creator>Jerry Satpathy</dc:creator>
      <pubDate>Wed, 04 Feb 2026 06:43:47 +0000</pubDate>
      <link>https://dev.to/j3rry320/the-day-my-linux-server-started-distributing-windows-malware-8jg</link>
      <guid>https://dev.to/j3rry320/the-day-my-linux-server-started-distributing-windows-malware-8jg</guid>
      <description>&lt;p&gt;&lt;em&gt;Here's a Minimal &amp;amp; Practical Guide to Server Hygiene&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you run a server long enough, you will eventually open a directory, spot a file you don't recognise, and think:&lt;/strong&gt; &lt;em&gt;“I did not put this here.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I had my &lt;em&gt;"moment"&lt;/em&gt; during the &lt;strong&gt;React2shell (CVE-2025-55182) outbreak&lt;/strong&gt;. I found a file named &lt;strong&gt;Agtisx.exe&lt;/strong&gt; sitting in a temp folder. A Windows executable on a Linux box is a red flag big enough to cover a stadium.&lt;/p&gt;

&lt;p&gt;It wasn't just a stray file; it was the payload for a campaign turning my infrastructure into a distribution hub to infect Windows servers. &lt;strong&gt;My clean server had become a staging ground for someone else’s war.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This guide exists so that the moment becomes mildly interesting instead of emotionally devastating. &lt;strong&gt;We aren't aiming for "military-grade" complexity. We want clean, boring, predictable systems that let you sleep at night.&lt;/strong&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%2Fzlhcmhp2o9bic0sc1291.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%2Fzlhcmhp2o9bic0sc1291.jpg" alt="Boring Predictable Systems" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. SSH: Make Logging In Aggressively Boring
&lt;/h2&gt;

&lt;p&gt;If logging into your server feels exciting, you’ve already failed. Your job isn't to defeat "hackers"; it’s to make your server so unrewarding that they move on to someone else.&lt;/p&gt;

&lt;p&gt;Your config file at &lt;code&gt;(/etc/ssh/sshd_config)&lt;/code&gt; should at the very least enforce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Key-based login only.&lt;/strong&gt; No passwords. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No root login.&lt;/strong&gt; Force a standard user. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimal attempts&lt;/strong&gt;. Give them three tries, then kick them.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#Edit /etc/ssh/sshd_config with these settings:&lt;/span&gt;
PasswordAuthentication no
PermitRootLogin no
PubkeyAuthentication &lt;span class="nb"&gt;yes
&lt;/span&gt;MaxAuthTries 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it works&lt;/strong&gt;: Bots love low-hanging fruit (passwords and root). They hate keys and effort. Be the effort.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Keys &amp;amp; Secret Rotation is Hygiene, Not Panic
&lt;/h2&gt;

&lt;p&gt;SSH keys live forever unless you actively rotate them. They sit on old laptops, archived backups, CI machines you no longer use, and devices you forgot ever had access.&lt;/p&gt;

&lt;p&gt;Environment variables behave the same way.&lt;/p&gt;

&lt;p&gt;Once a secret exists, it tends to spread. It gets copied into &lt;code&gt;.env&lt;/code&gt; files, pasted into dashboards, shared with teammates, backed up, and sometimes logged by mistake. Over time, you stop remembering where it lives, but it still works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rotating keys and secrets is not a response to an incident. It is routine maintenance. It limits the damage of forgotten access and reduces the blast radius of mistakes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you are thinking, “But nothing bad happened,” that is exactly the point. Rotation is what keeps it that way.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The Local Firewall: Trust but Verify
&lt;/h2&gt;

&lt;p&gt;Even if your cloud provider has a &lt;em&gt;"Security Group,"&lt;/em&gt; run a local firewall. It’s your second line of defence against human error—specifically, your own misclicks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Rule:&lt;/strong&gt; Expose SSH, HTTP, HTTPS, and your specific app ports. Block everything else.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Example using UFW (Uncomplicated Firewall)&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw default deny incoming
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow ssh
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow http
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow https
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw &lt;span class="nb"&gt;enable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Fail2ban: Outsource the Annoyance
&lt;/h2&gt;

&lt;p&gt;Brute-force attempts are a fact of life. You aren't being targeted; you just exist. Fail2ban watches your logs and quietly jails IPs that behave poorly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check status of blocked IPs&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;fail2ban-client status sshd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Audit Your Services
&lt;/h2&gt;

&lt;p&gt;Malware loves persistence, and persistence loves services. Run this command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl list-unit-files --state=enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Ask one question for every line: &lt;strong&gt;“Do I know why this is here?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;If the answer is No: Investigate.&lt;br&gt;
If the answer is still No: Disable it.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  6. The Post-Moment Forensic Routine
&lt;/h2&gt;

&lt;p&gt;When you find a file like Agtisx.exe, don't just delete it. You need to know how it got there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Check the Metadata&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before deleting, look at the file's &lt;em&gt;"birth certificate":&lt;/em&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;stat Agtisx.exe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This tells you the exact second it was created (Birth) or modified. Note the timestamp.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Check Permissions and Ownership&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Who &lt;em&gt;"owns"&lt;/em&gt; the malware?&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls -la Agtisx.exe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Owned by www-data? Your web app was the entry point (e.g., React2shell).&lt;br&gt;
Owned by root?This implies privilege escalation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Confirm via Logs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Match the stat timestamp against your logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Search web logs for activity around the 'stat' timestamp&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"2025-02-04 10:30"&lt;/span&gt; /var/log/nginx/access.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Recovery: The "Burn It Down" Philosophy
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Once a server is compromised enough to host attack payloads, you can rarely trust the OS again.&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Snapshot the evidence&lt;/strong&gt;: Save logs and the malware sample to an isolated folder.&lt;/li&gt;
&lt;li&gt;Rotate everything:

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SSH Keys: Generate new ones; revoke all old ones.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Secrets: Change DB passwords, API keys, and .env files.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delete the instance&lt;/strong&gt;: Terminate the server. Do not try to "clean" it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redeploy Fresh&lt;/strong&gt;: Provision a new instance, apply your "Boring Config," and patch the vulnerability (e.g., update React) before going live.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  8. Predictability Beats Fancy Tools
&lt;/h2&gt;

&lt;p&gt;Your server should only talk to places you expect. Check your active connections:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ss -antp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Normal&lt;/strong&gt;: Web traffic, database connections, updates.&lt;br&gt;
&lt;strong&gt;Not Normal:&lt;/strong&gt; Random IPs, unknown processes, strange ports.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. File Hygiene: Stop the Clutter
&lt;/h2&gt;

&lt;p&gt;Your server is not a downloads folder. Make sure to check if there are &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No random binaries in home directories.&lt;/li&gt;
&lt;li&gt; No world-writable directories. &lt;/li&gt;
&lt;li&gt;No executable permissions unless required.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Find world-writable directories&lt;/span&gt;
find / &lt;span class="nt"&gt;-xdev&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; d &lt;span class="se"&gt;\(&lt;/span&gt; &lt;span class="nt"&gt;-perm&lt;/span&gt; &lt;span class="nt"&gt;-0002&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-perm&lt;/span&gt; &lt;span class="nt"&gt;-1000&lt;/span&gt; &lt;span class="se"&gt;\)&lt;/span&gt; &lt;span class="nt"&gt;-print&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  10. Backups: The Disaster Circuit-Breaker
&lt;/h2&gt;

&lt;p&gt;Backups don’t prevent incidents; they prevent disasters. They turn a &lt;strong&gt;"compromise" into a "recovery."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Golden Rule&lt;/strong&gt;: If the thought of restoring your server feels scary, your backups aren't finished yet.&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%2Ff1jqfh4ihm0km64rz7ke.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%2Ff1jqfh4ihm0km64rz7ke.jpg" alt="Clean Predictable Systems" width="800" height="532"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;The Goal&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A clean server has:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A few ways in.&lt;/li&gt;
&lt;li&gt; A few things are running.&lt;/li&gt;
&lt;li&gt;Few places to hide.&lt;/li&gt;
&lt;li&gt;Predictable behaviour.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The best compliment a professional server can receive is: &lt;strong&gt;“Nothing interesting happened today.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The goal is to build for boredom &amp;amp; to Sleep better.&lt;br&gt;
And as always &lt;strong&gt;Happy Coding!&lt;/strong&gt; &lt;/p&gt;

</description>
      <category>software</category>
      <category>programming</category>
      <category>security</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How I Built a Google Maps Scraper to Generate Leads for My New Agency (And Why I Open-Sourced It)</title>
      <dc:creator>Jerry Satpathy</dc:creator>
      <pubDate>Fri, 14 Nov 2025 06:19:13 +0000</pubDate>
      <link>https://dev.to/j3rry320/how-i-built-a-google-maps-scraper-to-generate-leads-for-my-new-agency-and-why-i-open-sourced-it-3lad</link>
      <guid>https://dev.to/j3rry320/how-i-built-a-google-maps-scraper-to-generate-leads-for-my-new-agency-and-why-i-open-sourced-it-3lad</guid>
      <description>&lt;p&gt;When you're building a brand-new agency, there’s one problem you can’t escape:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finding clients.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before we had a portfolio, before we had referrals, before anyone even knew our name — we needed a reliable way to identify businesses that might need websites, branding, software, or digital marketing.&lt;/p&gt;

&lt;p&gt;At &lt;strong&gt;&lt;a href="https://codemedialabs.in" rel="noopener noreferrer"&gt;Code Media Labs&lt;/a&gt;&lt;/strong&gt; — my newly formed agency — that responsibility fell on me.&lt;/p&gt;

&lt;p&gt;And like many new founders, I turned to the simplest place to find businesses:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Google Maps.&lt;/strong&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%2F9ya1sgh19w8g0oqz50o1.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%2F9ya1sgh19w8g0oqz50o1.png" alt="Google Maps The OG Lead Generator Machine" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  The Struggle Every New Agency Knows
&lt;/h2&gt;

&lt;p&gt;If you've ever done manual prospecting, you know the routine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Search “Interior Designers near me”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scroll, scroll, scroll&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click each listing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy the name, phone, rating, URL&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Paste into a spreadsheet&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Repeat 150+ times&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s slow. It's painful. And it steals hours from the work that actually builds your agency.&lt;/p&gt;

&lt;p&gt;One night — after manually extracting yet another list — I said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Enough. I’m automating this.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And that turned into a tool that helped my agency survive its early months.&lt;/p&gt;


&lt;h2&gt;
  
  
  From Internal Hack → Lead Machine
&lt;/h2&gt;

&lt;p&gt;I opened VS Code and wrote a small Puppeteer script:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Launch Google Maps&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Search for a keyword&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scroll automatically&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extract business details&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save everything cleanly&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first version was rough. But it worked.&lt;/p&gt;

&lt;p&gt;I could instantly generate lists like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cafes in Cuttack&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Marketing agencies in Bhubaneswar&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retail shops in Saheed Nagar&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Manufacturers across Odisha&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a brand-new agency, this sped up our outreach dramatically.&lt;br&gt;&lt;br&gt;
Instead of spending hours gathering data, I could spend hours pitching and closing.&lt;/p&gt;
&lt;h2&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%2Ftplyvynoaorx9fw6d8bz.png" alt="Every Developer Automates Every Single Task" width="800" height="800"&gt;
&lt;/h2&gt;
&lt;h2&gt;
  
  
  Why I Decided to Open-Source It
&lt;/h2&gt;

&lt;p&gt;Initially, the scraper was private — a purely internal survival tool.&lt;br&gt;&lt;br&gt;
But the more I talked to other freelancers and small agencies, the more I realised:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Everyone is struggling with lead generation, especially early on.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I cleaned up the tool, added a CLI, refined the output, wrote proper documentation, and published it.&lt;/p&gt;

&lt;p&gt;Originally, I wanted to publish it as a scoped package (&lt;code&gt;@cml/google-maps-scraper&lt;/code&gt;), but scoped namespaces are paid.&lt;br&gt;&lt;br&gt;
So I renamed it clean and simple:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;code&gt;gmaps-scraper&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A free, open-source Google Maps scraping tool for everyone.&lt;/p&gt;

&lt;p&gt;NPM: &lt;a href="https://www.npmjs.com/package/gmaps-scraper" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/gmaps-scraper&lt;/a&gt;&lt;br&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/Code-Media-Labs/google-maps-scraper" rel="noopener noreferrer"&gt;https://github.com/Code-Media-Labs/google-maps-scraper&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  What the Tool Can Do
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;🔍 Scrape &lt;em&gt;any&lt;/em&gt; Google Maps query&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🏪 Extract business details (name, rating, reviews, phone, URL)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🔁 Auto-scroll until all results are loaded&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🛡 Automatically deduplicate entries&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;📦 Export results to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;results.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;results.xlsx&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;🧰 Use as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  A CLI command&lt;/li&gt;
&lt;li&gt;  A Node.js importable library&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For freelancers and new agencies, this is a huge time-saver.&lt;/p&gt;


&lt;h2&gt;
  
  
  How to Use It
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Global (CLI usage):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; gmaps-scraper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Local (project usage):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;gmaps-scraper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  CLI Usage
&lt;/h2&gt;

&lt;p&gt;Search for all interior designers in Bhubaneswar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gmaps-scraper scrape &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"Interior Designers in Bhubaneswar"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Custom output path:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gmaps-scraper scrape &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"Cafes in Cuttack"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; cafes.json 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Headless mode + limited scrolls:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gmaps-scraper scrape &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"Hotels in Puri"&lt;/span&gt; &lt;span class="nt"&gt;--headless&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; 50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💻 Library Usage (Node.js)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;scrapeGoogleMaps&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt;  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gmaps-scraper&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="k"&gt;await&lt;/span&gt;  &lt;span class="nf"&gt;scrapeGoogleMaps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;

&lt;span class="na"&gt;searchQuery&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cafes in Cuttack&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="na"&gt;outputPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cafes.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="na"&gt;maxScrollAttempts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="na"&gt;headless&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Found &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; cafes`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"Urban Café"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"rating"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"4.5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"reviews_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"1,204"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"+91 9876543210"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"maps_link"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"https://www.google.com/maps/place/..."&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Real Talk: Google Maps Can Break Your Selectors
&lt;/h2&gt;

&lt;p&gt;Scraping Google Maps isn't &lt;em&gt;“set-and-forget.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Google changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;class names&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;container structure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;layout&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;nested DOM elements&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your selectors may break.&lt;br&gt;&lt;br&gt;
But fixing them is simple if you know what to look for.&lt;/p&gt;

&lt;h3&gt;
  
  
  Old selector:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;const name = await element.$eval('.business-name', el =&amp;gt; el.textContent);&lt;/code&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Updated selector:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;const name = await element.$eval('.place-title span', el =&amp;gt; el.textContent);&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;Whenever Google makes a UI update, just inspect again and adjust your selectors.&lt;/p&gt;




&lt;h2&gt;
  
  
  Who Should Use This?
&lt;/h2&gt;

&lt;p&gt;This tool is built for anyone who needs structured business data from Google Maps — especially if you’re trying to grow or automate your workflow. You’ll benefit from this scraper if you are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A new agency&lt;/strong&gt; looking for qualified leads quickly&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A freelancer&lt;/strong&gt; who wants to find clients without spending hours searching manually&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A marketer&lt;/strong&gt; needing business lists for outreach, campaigns, or segmentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A founder&lt;/strong&gt; validating a market or researching local competitors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;An SEO specialist&lt;/strong&gt; creating or updating business directories&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A developer&lt;/strong&gt; building automation tools, dashboards, or datasets&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A data analyst&lt;/strong&gt; collecting local business information for insights&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re early in your journey and want to save time, remove repetitive work, and scale your lead generation, this tool gives you a massive head start.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Coming Next
&lt;/h2&gt;

&lt;p&gt;I’m actively adding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Address, website, and business hours extraction&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anti-detection and rate-limiting features&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Region/language support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cleaner error handling&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CSV and CRM-friendly output formats&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to contribute, PRs are welcome!&lt;/p&gt;




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

&lt;p&gt;When you're building a new agency, every hour counts.&lt;br&gt;&lt;br&gt;
This tool saved me countless hours of lead generation — and helped bring in our earliest clients.&lt;/p&gt;

&lt;p&gt;That’s why I open-sourced it.&lt;br&gt;&lt;br&gt;
If it helps someone else who’s just starting, it’s worth it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you’ve built an internal tool that saved you time… consider open-sourcing it. You might help someone who’s exactly where you were.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  And as always, Happy Coding 🧑🏻‍💻
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Built with ❤️ by &lt;a href="https://codemedialabs.in" rel="noopener noreferrer"&gt;Code Media Labs&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How to Use the CSS aspect-ratio Property for Responsive Layouts</title>
      <dc:creator>Jerry Satpathy</dc:creator>
      <pubDate>Sun, 28 Sep 2025 14:47:53 +0000</pubDate>
      <link>https://dev.to/j3rry320/how-to-use-the-css-aspect-ratio-property-for-responsive-layouts-20pd</link>
      <guid>https://dev.to/j3rry320/how-to-use-the-css-aspect-ratio-property-for-responsive-layouts-20pd</guid>
      <description>&lt;p&gt;&lt;strong&gt;As front-end developers&lt;/strong&gt;, we’ve all battled with &lt;em&gt;awkwardly stretched images&lt;/em&gt;, mysteriously squashed video embeds, or divs that seem to believe geometry is optional. Enter CSS’s &lt;code&gt;aspect-ratio&lt;/code&gt; property, &lt;em&gt;our knight in shining layout armour.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This property has quickly become a modern CSS favourite. It lets us maintain proportionate layouts without relying on padding hacks, JavaScript workarounds, or &lt;em&gt;obscure "magic numbers."&lt;/em&gt; Let’s dive into how it works and why it changes the game.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is aspect-ratio?
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;aspect-ratio&lt;/code&gt; property &lt;strong&gt;allows you to control the ratio between an element’s width and height.&lt;/strong&gt; Instead of hardcoding both dimensions, you define the relationship, and the browser does the rest.&lt;/p&gt;

&lt;p&gt;Here’s the syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.element&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;aspect-ratio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;16 / 9&lt;/code&gt;probably looks familiar. It’s the widescreen video ratio. You can also set it to &lt;code&gt;1 / 1&lt;/code&gt; for a perfect square or &lt;code&gt;21 / 9&lt;/code&gt; if you want something more &lt;em&gt;cinematic.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is aspect-ratio Useful?
&lt;/h2&gt;

&lt;p&gt;Before this property, developers had to rely on clever but &lt;em&gt;hacky tricks&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using padding-top percentages, such as &lt;strong&gt;56.25%&lt;/strong&gt; for a &lt;strong&gt;16:9 ratio (since 9 ÷ 16 = 0.5625).&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Calculating and setting height with &lt;strong&gt;JavaScript&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faking ratios&lt;/strong&gt; with background images.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These approaches got the job done, but they were messy and didn’t always play well with responsive design. Now, &lt;em&gt;you can write one clean line of CSS and move on with your life.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does It Actually Work?
&lt;/h2&gt;

&lt;p&gt;Think of aspect-ratio as a rule that says: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“No matter what, keep these proportions.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;If only the &lt;strong&gt;width is set&lt;/strong&gt;, the &lt;strong&gt;height automatically adjusts.&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;If only the &lt;strong&gt;height is set,&lt;/strong&gt; the &lt;strong&gt;width adjusts&lt;/strong&gt;. &lt;/li&gt;
&lt;li&gt;If &lt;strong&gt;both are set explicitly&lt;/strong&gt;, &lt;strong&gt;aspect-ratio keeps quiet&lt;/strong&gt; and steps aside.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example with width and ratio:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.video-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;aspect-ratio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#eee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;strong&gt;the width fills the parent, and the height follows along smoothly&lt;/strong&gt; at the correct ratio.&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%2Fxryyybx9i7n6uskriwuz.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%2Fxryyybx9i7n6uskriwuz.png" alt="Aspect ratio to the rescue" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Applications
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Video embeds:&lt;/strong&gt; YouTube and Vimeo iframes that stay perfectly proportioned.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Image grids:&lt;/strong&gt; Thumbnails that don’t squish or stretch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cards and placeholders:&lt;/strong&gt; Consistent layouts even without real content inside.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brand consistency&lt;/strong&gt;: Great for product photos where the visual style needs to stay uniform.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Combining with Other CSS Properties
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;aspect-ratio&lt;/code&gt; property pairs really well with other layout tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;aspect-ratio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;object-fit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cover&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you’ve got a consistently shaped card that looks clean and scales gracefully.&lt;/p&gt;

&lt;h2&gt;
  
  
  Browser Support
&lt;/h2&gt;

&lt;p&gt;The best part is that modern browsers have supported it very well &lt;strong&gt;since 2021&lt;/strong&gt;. You don’t need to polyfill or worry about strange quirks. And since Internet Explorer has retired, &lt;em&gt;we can enjoy this feature with a lot less stress&lt;/em&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%2Fzz8qt45v2l1eid48sr4j.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%2Fzz8qt45v2l1eid48sr4j.png" alt="Designing the web" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Quick Analogy
&lt;/h2&gt;

&lt;p&gt;Think of &lt;code&gt;aspect-ratio&lt;/code&gt; as the reliable friend in group photos. They’re never the ones who look unnaturally stretched or squeezed. While others get complicated, &lt;strong&gt;aspect-ratio just keeps everything looking balanced.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;aspect-ratio&lt;/code&gt; property &lt;strong&gt;may feel small at first&lt;/strong&gt;, but it &lt;strong&gt;quietly solves one of the longest-running pain points in web design&lt;/strong&gt;. It saves time, removes the need for hacks, and makes &lt;strong&gt;responsive design&lt;/strong&gt; a little more fun.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you haven’t used it yet, try adding aspect-ratio into your next project and see how much easier it makes layout work.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And as always, &lt;strong&gt;&lt;em&gt;Happy Coding!&lt;/em&gt;&lt;/strong&gt; 👾&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>css</category>
      <category>web</category>
    </item>
    <item>
      <title>JSDoc: Your Secret Weapon for Adding Types to JavaScript (Without the Full TypeScript Overhaul)</title>
      <dc:creator>Jerry Satpathy</dc:creator>
      <pubDate>Sat, 15 Feb 2025 12:01:58 +0000</pubDate>
      <link>https://dev.to/j3rry320/jsdoc-your-secret-weapon-for-adding-types-to-javascript-without-the-full-typescript-overhaul-3n20</link>
      <guid>https://dev.to/j3rry320/jsdoc-your-secret-weapon-for-adding-types-to-javascript-without-the-full-typescript-overhaul-3n20</guid>
      <description>&lt;p&gt;&lt;strong&gt;TypeScript is a fantastic tool for adding static typing to JavaScript&lt;/strong&gt;, catching errors early and making large codebases more manageable.  But let's be honest, sometimes a &lt;strong&gt;full TypeScript migration can feel like climbing Mount Everest&lt;/strong&gt;.  What if you could get most of the benefits of a statically typed system without the complete overhaul?  &lt;strong&gt;Enter JSDoc, your secret weapon for adding types&lt;/strong&gt; (and excellent documentation!) to your JavaScript projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Power of JSDoc
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;JSDoc, those familiar comments above your code&lt;/strong&gt;, can do more than explain what your functions do.  They can also define types! Using &lt;code&gt;@typedef&lt;/code&gt; and &lt;code&gt;@type&lt;/code&gt; you can create complex, &lt;strong&gt;reusable type definitions in your JavaScript files&lt;/strong&gt;.  This allows you to add type safety and improve code readability without the full complexity of TypeScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why JSDoc Might Be Right for You
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Smaller Projects&lt;/strong&gt;: For smaller projects, the overhead of a full TypeScript setup might be overkill. JSDoc offers a lightweight way to add structure and documentation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gradual Adoption&lt;/strong&gt;: JSDoc can be a fantastic stepping stone towards TypeScript. You can start with JSDoc, generate declaration files, and gradually transition to full TypeScript if needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Existing JavaScript Codebases&lt;/strong&gt;: Migrating a massive JavaScript codebase to TypeScript can be daunting. JSDoc allows you to introduce types incrementally, without rewriting everything at once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation as a First-Class Citizen&lt;/strong&gt;: JSDoc emphasizes documentation, which is crucial regardless of your typing system. A well-documented codebase is always a plus.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Defining Types with &lt;code&gt;@typedef&lt;/code&gt; and &lt;code&gt;@type&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Here's where the magic happens.  Let's see how you define types using JSDoc:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="cm"&gt;/**
 * @typedef {Object} Point
 * @property {number} x - The x-coordinate.
 * @property {number} y - The y-coordinate.
 */&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Calculates the distance between two points.
 * @param {Point} p1 - The first point.
 * @param {Point} p2 - The second point.
 * @returns {number} The distance between the points.
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;dy&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * @type {Point}
 */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originPoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originPoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In this example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@typedef {Object} Point&lt;/code&gt;: &lt;strong&gt;Defines a Point type as an object with x and y properties, both numbers&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@param {Point} p1&lt;/code&gt;: &lt;strong&gt;Uses the Point type to specify the type of the p1 parameter&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@param {Point} p2&lt;/code&gt;: &lt;strong&gt;Uses the Point type to specify the type of the p2 parameter&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@type {Point}&lt;/code&gt;: &lt;strong&gt;Annotates the originPoint constant with the Point type&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Generating &lt;code&gt;.d.ts&lt;/code&gt; Files
&lt;/h2&gt;

&lt;p&gt;The real &lt;strong&gt;power of JSDoc&lt;/strong&gt; types comes when you &lt;strong&gt;generate TypeScript declaration files (.d.ts)&lt;/strong&gt;.  The TypeScript compiler (tsc) can parse your JSDoc comments and create these files for you.  This means you get type-checking and code completion in your IDE, even while writing plain JavaScript!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Here's the basic &lt;code&gt;tsconfig.json&lt;/code&gt; configuration:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"es2020"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"commonjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"declaration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allowJs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"emitDeclarationOnly"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ONLY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;emit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;.d.ts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;files&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"esModuleInterop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"./src/**/*.js"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exclude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"node_modules"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Then, run &lt;code&gt;npx tsc&lt;/code&gt; (or &lt;code&gt;tsc&lt;/code&gt; if installed globally) in your project directory.  This will generate the &lt;code&gt;.d.ts&lt;/code&gt; files in your outDir (./dist in this example). Below you can see the declaration file tsc generates for you&lt;/strong&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%2Ftes4w6xy3gyr36i3cyjc.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%2Ftes4w6xy3gyr36i3cyjc.png" alt="The generated declaration file for our example" width="800" height="920"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Best of Both Worlds
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;JSDoc&lt;/strong&gt; with type generation &lt;strong&gt;provides a fantastic middle ground&lt;/strong&gt;. You can enjoy the benefits of type safety and improved documentation without the full overhead of TypeScript.  It's a great option for projects where &lt;strong&gt;a complete TypeScript migration isn't feasible or necessary&lt;/strong&gt;, allowing you to gradually introduce types and improve your code quality over time.&lt;/p&gt;

&lt;p&gt;So, &lt;strong&gt;next time you're thinking about adding types to your JavaScript&lt;/strong&gt;, don't immediately jump to a full TypeScript conversion. &lt;strong&gt;Consider JSDoc&lt;/strong&gt; – it might be exactly what you need.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And as always&lt;/em&gt; &lt;br&gt;
&lt;strong&gt;Happy Coding&lt;/strong&gt; 🧑🏻‍💻&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>typescript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Effortlessly Generate Professional Videos with AI-Powered Clip-Creator CLI</title>
      <dc:creator>Jerry Satpathy</dc:creator>
      <pubDate>Sat, 01 Feb 2025 05:18:17 +0000</pubDate>
      <link>https://dev.to/j3rry320/create-professional-videos-in-minutes-with-ai-powered-clip-creator-cli-413g</link>
      <guid>https://dev.to/j3rry320/create-professional-videos-in-minutes-with-ai-powered-clip-creator-cli-413g</guid>
      <description>&lt;p&gt;In today's digital age, &lt;strong&gt;video content is king&lt;/strong&gt;. Whether you're a content creator, marketer, educator, or social media enthusiast, producing high-quality videos that engage and captivate your audience is crucial. However, the process of creating these videos &lt;em&gt;can often be time-consuming and complex&lt;/em&gt;. Enter Clip-Creator CLI - a groundbreaking command-line interface tool that leverages the power of AI to &lt;strong&gt;simplify and revolutionize video creation&lt;/strong&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%2Foieq9k7i3buh825hitjn.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%2Foieq9k7i3buh825hitjn.png" alt="Clip-Creator CLI" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating high-quality video content has never been easier and cheaper&lt;/strong&gt;, thanks to the innovative Clip-Creator CLI. This open-source command-line tool leverages the power of LLMs to generate engaging video clips, complete with audio and scripts, in just a few simple steps. Whether you are a content creator, marketer, or educator, Clip-Creator CLI is here to &lt;em&gt;transform your video production process&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use Clip-Creator CLI?
&lt;/h2&gt;

&lt;p&gt;In a world where video content reigns supreme, standing out requires both quality and efficiency. Clip-Creator CLI provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI-Powered Script Generation&lt;/strong&gt;: Let advanced AI models handle the scriptwriting, ensuring engaging and relevant content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Video Creation&lt;/strong&gt;: Customize video parameters to suit your needs, from duration to content category.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diverse Content Categories and Tones&lt;/strong&gt;: Match your video’s style and message with a wide range of categories and tones.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High-Quality Audio&lt;/strong&gt;: Enhance your videos with premium audio tracks sourced from FreeSound.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High-Definition Visuals&lt;/strong&gt;: Access a vast library of stunning visuals from Pexels to make your content visually appealing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fact-Checking Support&lt;/strong&gt;: Keep your content accurate and trustworthy with built-in fact-checking features.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User-Friendly Web Interface&lt;/strong&gt;: Seamlessly navigate through the video creation process with an intuitive web UI.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Clip-Creator CLI Can Automate Your Social Media Video Generation
&lt;/h2&gt;

&lt;p&gt;Clip-Creator CLI isn't just about creating standalone videos; it can be integrated with other services to automate your social media video generation process. Here are some ways to get the most out of it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Text-to-Speech (TTS) Services: Integrate with TTS APIs to automatically add realistic voiceovers to your videos. Whether it's a tutorial or a marketing video, TTS can bring your scripts to life.&lt;/li&gt;
&lt;li&gt;Social Media APIs: Use APIs to automatically post your videos to social media platforms. Schedule posts, track engagement, and streamline your social media strategy without lifting a finger.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Free and Efficient Content Creation
&lt;/h2&gt;

&lt;p&gt;One of the best things about Clip-Creator CLI is that you can &lt;strong&gt;generate videos for free using Pexels and FreeSound APIs&lt;/strong&gt;. As long as you respect the rate limits of these services, you can access a wealth of high-quality visuals and audio tracks without any cost. Additionally, &lt;strong&gt;leveraging large language models (LLMs) within the usage limits&lt;/strong&gt; allows you to keep the content creation process efficient and cost-effective.&lt;/p&gt;

&lt;h2&gt;
  
  
  Total Video Creation Capacity
&lt;/h2&gt;

&lt;p&gt;On average, you can create approximately &lt;strong&gt;1600-10,000&lt;/strong&gt; &lt;em&gt;videos per month for free&lt;/em&gt; using Clip-Creator CLI. This estimate assumes balanced usage across all APIs and adherence to their respective rate limits.&lt;/p&gt;

&lt;p&gt;Unleash your creativity and start producing a substantial volume of high-quality videos effortlessly!&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;To start creating amazing video content with Clip-Creator CLI, follow these simple steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install Clip-Creator CLI:&lt;/strong&gt;&lt;br&gt;
Install the package using npm or yarn or npx&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; clip-creator
&lt;span class="c"&gt;#or &lt;/span&gt;
yarn add global clip-creator 
&lt;span class="c"&gt;#or &lt;/span&gt;
npx clip-creator &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Configure Your API Keys:&lt;/strong&gt;&lt;br&gt;
To get started, create a configuration file containing your API keys along with any other default or advanced configurations you wish to pass to the package. This ensures that the video creation process is seamless and tailored to your needs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"freeSoundApiKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"groqApiKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"pexelsApiKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-key"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Generate Your First Video Clip:&lt;/strong&gt; &lt;br&gt;
Customize your video creation by specifying parameters that suit your requirements. Use the configuration file you created to streamline the process, or you can pass the configuration interactively via the CLI&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clip-creator create &lt;span class="nt"&gt;--category&lt;/span&gt; &lt;span class="s2"&gt;"Educational"&lt;/span&gt; &lt;span class="nt"&gt;--tone&lt;/span&gt; &lt;span class="s2"&gt;"Professional"&lt;/span&gt; &lt;span class="nt"&gt;--topic&lt;/span&gt; &lt;span class="s2"&gt;"Rise of AI"&lt;/span&gt; &lt;span class="nt"&gt;--duration&lt;/span&gt; 30 &lt;span class="nt"&gt;--config&lt;/span&gt; /path/to/config.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Tip: Remember, the order of precedence is: Command Line Interface (CLI) -&amp;gt; Config File -&amp;gt; Interactive Prompt. This means that any parameters specified in the CLI will override those in the config file, and those in the config file will override interactive prompts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Interactive Configuration&lt;/strong&gt;&lt;br&gt;
If you prefer not to create a configuration file or pass parameters via the CLI, you can directly run the clip-creator create command to interactively input all necessary configurations. This mode will prompt you for each required detail, ensuring a smooth and guided setup process.&lt;/p&gt;

&lt;p&gt;Simply run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clip-creator create
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will walk you through setting up your video creation parameters interactively, making it convenient for users who prefer a hands-on approach without pre-setting configurations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Launch the Web Interface
&lt;/h2&gt;

&lt;p&gt;To start the web interface and enjoy a user-friendly experience, follow these steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start the Web Interface:&lt;/strong&gt;&lt;br&gt;
Run the following command to launch the web interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clip-creator web &lt;span class="nt"&gt;--port&lt;/span&gt; 3003
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Open Your Browser:&lt;/strong&gt; &lt;br&gt;
After starting the web interface, open your web browser and navigate to:&lt;br&gt;
&lt;a href="http://localhost:3003/index.html" rel="noopener noreferrer"&gt;http://localhost:3003/index.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will bring up the web-based UI, where you can visualize and manage your video creation process seamlessly. The web interface provides a clean and intuitive environment, allowing you to see the output and make any necessary adjustments interactively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Involved
&lt;/h2&gt;

&lt;p&gt;We invite the community to contribute, improve, and use Clip-Creator CLI. It’s open-source and available under the MIT license. For professional inquiries or to hire the author, visit my &lt;a href="https://www.linkedin.com/in/jerrythejsguy/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Clip-Creator CLI is your go-to tool for creating professional-grade videos with minimal effort&lt;/strong&gt;. Leveraging AI and seamless integration with top content sources, it has never been easier to produce stunning videos. Get started with Clip-Creator CLI today and elevate your content creation to new heights!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>javascript</category>
      <category>tooling</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Introducing Markdown Parser React v2.0.0: Your Go-To Markdown Rendering Solution</title>
      <dc:creator>Jerry Satpathy</dc:creator>
      <pubDate>Mon, 20 Jan 2025 11:01:40 +0000</pubDate>
      <link>https://dev.to/j3rry320/introducing-markdown-parser-react-v200-your-go-to-markdown-rendering-solution-1ii5</link>
      <guid>https://dev.to/j3rry320/introducing-markdown-parser-react-v200-your-go-to-markdown-rendering-solution-1ii5</guid>
      <description>&lt;p&gt;If you've ever worked with Markdown in a React or a Next.js application, you know how important it is to have a robust and customizable parser. That’s why, I’m thrilled to introduce the newest version of Markdown Parser React—a feature-rich, easy-to-use, and highly customizable React component for rendering Markdown content in your applications. &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%2F0h9v6cfybc92ozlfa65x.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%2F0h9v6cfybc92ozlfa65x.png" alt="markdown-parser-react" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Markdown Parser React? 🤔
&lt;/h2&gt;

&lt;p&gt;Whether you’re building a blog, a documentation platform, or an interactive dashboard, Markdown Parser React offers everything you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Full Markdown Support&lt;/strong&gt;: From headers and links to tables and code blocks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable Styling&lt;/strong&gt;: Tailor the look and feel to match your brand or project theme.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility&lt;/strong&gt;: Designed with ARIA attributes for better screen reader support.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extended Features&lt;/strong&gt;: Task lists, definition lists, syntax highlighting, math equations, and more!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inline and Block Rendering&lt;/strong&gt;: Handle both inline Markdown (e.g., bold text, math equation, underlined text) and block elements (e.g., tables and lists).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lightweight and Fast&lt;/strong&gt;: Optimized for performance to keep your app snappy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started 📦
&lt;/h2&gt;

&lt;p&gt;You can install Markdown Parser React in your project using npm, yarn, or pnpm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;markdown-parser-react

&lt;span class="c"&gt;# or&lt;/span&gt;

yarn add markdown-parser-react

&lt;span class="c"&gt;# or&lt;/span&gt;

pnpm add markdown-parser-react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Basic Usage 🛠️
&lt;/h2&gt;

&lt;p&gt;Rendering Markdown content is as easy as this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Markdown&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;markdown-parser-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Markdown&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;"#&lt;/span&gt; &lt;span class="na"&gt;Hello&lt;/span&gt; &lt;span class="na"&gt;World&lt;/span&gt;
&lt;span class="na"&gt;This&lt;/span&gt; &lt;span class="na"&gt;is&lt;/span&gt; &lt;span class="err"&gt;**&lt;/span&gt;&lt;span class="na"&gt;Markdown&lt;/span&gt;&lt;span class="err"&gt;**!"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advanced Features 🔥
&lt;/h2&gt;

&lt;p&gt;Markdown Parser React shines when you want to customize your Markdown rendering. Here’s how you can configure it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Markdown&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;markdown-parser-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;BlogPost&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;markdownContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
# Welcome to My Blog  

This is a _formatted_ paragraph with a [link](https://example.com).

- [x] Task 1
- [ ] Task 2

&lt;/span&gt;&lt;span class="se"&gt;\`\`\`&lt;/span&gt;&lt;span class="s2"&gt;javascript
console.log("Hello, Markdown!");
&lt;/span&gt;&lt;span class="se"&gt;\`\`\`&lt;/span&gt;&lt;span class="s2"&gt;

| Column 1 | Column 2 |
|----------|----------|
| Cell 1   | Cell 2   |
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Markdown&lt;/span&gt;
      &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;markdownContent&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;customClasses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;headings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blog-heading&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;paragraphs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blog-paragraph&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;customStyles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;headings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#2c3e50&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fontFamily&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Georgia, serif&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;linkTarget&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_blank&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;sanitizeHtml&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;maxNestingLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"blog-content"&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Features Highlight:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Custom CSS Classes&lt;/strong&gt;: Assign specific CSS classes to headings, paragraphs, and more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom CSS Styles&lt;/strong&gt;: Assign specific styles to headings, paragraphs, and more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safe HTML Rendering&lt;/strong&gt;: Protects your app from potential security threats.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessible by Default&lt;/strong&gt;: Includes ARIA labels for better UX.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Built for Modern Frameworks 🏗️
&lt;/h2&gt;

&lt;p&gt;If &lt;strong&gt;you’re using Next.js&lt;/strong&gt;, avoid server-client rendering mismatches by dynamically importing the Markdown component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;dynamic&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/dynamic&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Markdown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;markdown-parser-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ssr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Markdown&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Who Should Use Markdown Parser React? 🌟
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Developers building blogs or documentation sites.&lt;/li&gt;
&lt;li&gt;Content creators who need Markdown support in their React projects.&lt;/li&gt;
&lt;li&gt;Teams, requiring a secure and accessible Markdown rendering solution.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Join the Community
&lt;/h2&gt;

&lt;p&gt;Markdown Parser React is open-source and MIT-licensed. If you find it useful, consider giving it a ⭐️ on &lt;a href="https://github.com/J3rry320/markdown-parser-react" rel="noopener noreferrer"&gt;Github&lt;/a&gt;. Contributions and feedback are always welcome!&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Out Today!
&lt;/h2&gt;

&lt;p&gt;Don’t miss out on making your Markdown content shine in React. Install &lt;a href="https://www.npmjs.com/package/markdown-parser-react" rel="noopener noreferrer"&gt;Markdown Parser React&lt;/a&gt; today and supercharge your projects. &lt;/p&gt;

&lt;p&gt;What feature are you most excited about? &lt;em&gt;&lt;strong&gt;Let me know in the comments or share your thoughts on GitHub!&lt;/strong&gt;&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;Happy Coding 🧑🏻‍💻&lt;/p&gt;

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