<?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: Suryansh Swarn</title>
    <description>The latest articles on DEV Community by Suryansh Swarn (@suryansh_swarn).</description>
    <link>https://dev.to/suryansh_swarn</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%2F3931493%2F5e6454a4-57c1-4595-be0e-05ebfae58462.png</url>
      <title>DEV Community: Suryansh Swarn</title>
      <link>https://dev.to/suryansh_swarn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/suryansh_swarn"/>
    <language>en</language>
    <item>
      <title>How Do You Turn Raw NASA Satellite Streams into a High-Performance Geospatial Interface?</title>
      <dc:creator>Suryansh Swarn</dc:creator>
      <pubDate>Sat, 16 May 2026 08:23:49 +0000</pubDate>
      <link>https://dev.to/suryansh_swarn/how-do-you-turn-raw-nasa-satellite-streams-into-a-high-performance-geospatial-interface-3nlg</link>
      <guid>https://dev.to/suryansh_swarn/how-do-you-turn-raw-nasa-satellite-streams-into-a-high-performance-geospatial-interface-3nlg</guid>
      <description>&lt;p&gt;As developers, we routinely build dashboards for predictable data like server metrics or revenue funnels. But tracking volatile, live planetary anomalies is a completely different challenge. During natural hazards, critical telemetry is often fragmented across chaotic feeds, creating a dangerous systemic vulnerability for responders and researchers.&lt;/p&gt;

&lt;p&gt;To solve this, I engineered &lt;strong&gt;Disaster-map-NASA-EONET&lt;/strong&gt;—a tactical geospatial console designed to ingest, normalize, and render live global hazard data onto a high-performance, reactive map interface. Here is an architectural deep dive into how I overcame asynchronous data bottlenecks and built a client-side state that scales seamlessly.&lt;/p&gt;




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

&lt;p&gt;To ensure fluid frame rates and low rendering latency without the bloat of heavy commercial platforms, the application uses a highly optimized front-end pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React 19 &amp;amp; Vite 8:&lt;/strong&gt; Handles the core declarative UI architecture with concurrent rendering and hyper-fast development builds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leaflet &amp;amp; React-Leaflet:&lt;/strong&gt; Grants lightweight, direct client-side control over GIS rendering loops and tile layers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind CSS v4:&lt;/strong&gt; Utilizes the compile-time &lt;code&gt;@tailwindcss/vite&lt;/code&gt; engine to provide zero-runtime styling with minimal asset weight.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recharts:&lt;/strong&gt; Ingests raw statistical arrays to render multi-axis spatial telemetry and data charts.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Design System
&lt;/h2&gt;

&lt;p&gt;A tracking console is only as effective as its cognitive throughput. If the UI is cluttered, critical analytical insights get lost under the visual noise. I structured the application with a distinct "Control Room" aesthetic focused on high visual contrast and modern layering:&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%2Fjogshx6olhuyl677xegn.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%2Fjogshx6olhuyl677xegn.png" alt="Dark mode mockups" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Cinematic Mapping Layer:&lt;/strong&gt; Instead of standard map styles, I used Leaflet’s tile layers to craft a deep, dark slate environment. When active satellite mode is disabled, the map shifts to a monochrome space-black canvas, causing the bright warning indicators of active natural events to stand out vividly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Collapsible Control Deck:&lt;/strong&gt; The command sidebar leverages responsive, text-transformative utility styles and glassmorphic translucent paneling (&lt;code&gt;backdrop-blur-md&lt;/code&gt;). It overlays global data feeds, classification parameters, and real-time filters directly across the screen width without completely occluding the main tracking area.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Engineering Challenge
&lt;/h2&gt;

&lt;p&gt;The primary engineering obstacle when working with NASA's Earth Observatory Natural Event Tracker (EONET) API was managing &lt;strong&gt;Asynchronous Spatial Normalization&lt;/strong&gt; and &lt;strong&gt;Downstream Filtering&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Eliminating Redundant Network Load via Downstream Separation
&lt;/h3&gt;

&lt;p&gt;The API query returns thousands of natural events over a yearly timeline. Querying NASA's servers every time a user toggles a category filter would easily exhaust API rate limits, spike network bandwidth, and stall client rendering.&lt;/p&gt;

&lt;p&gt;To solve this, I designed a multi-tiered state loop:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An &lt;strong&gt;upstream network synchronizer&lt;/strong&gt; hooks onto chronological shifts (the year filter) to fetch the raw data snapshot into &lt;code&gt;allEvents&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A separate &lt;strong&gt;downstream effect&lt;/strong&gt; watches client-side categorical selections to filter the in-memory array locally. This completely eliminates unneeded network overhead, shifting the filtering complexity from an asynchronous $O(N)$ network request to a lightning-fast client-side operation.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  2. Normalizing Polygons into Standard Bounding Geometries
&lt;/h3&gt;

&lt;p&gt;Furthermore, the EONET database represents geographic features using uneven data models. Some hazards are specified via simple point coordinates, while massive events like hurricanes or wildfires are provided as complex Polygon coordinate grids.&lt;/p&gt;

&lt;p&gt;Passing a raw geometry array directly into a standard map marker breaks Leaflet, resulting in catastrophic application failures. I wrote defensive structural parsing logic to safely unpack multi-dimensional array indices down to fallback coordinates on the fly.&lt;/p&gt;

&lt;p&gt;Here is how the core orchestration is implemented in the codebase:&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="c1"&gt;// From App.jsx: Decoupled Upstream Networking &amp;amp; Downstream In-Memory Filtering&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;fetchEvents&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&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="c1"&gt;// Guard clause against empty category maps&lt;/span&gt;
    &lt;span class="nf"&gt;setIsLoading&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="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;try&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;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://eonet.gsfc.nasa.gov/api/v3/events/geojson?status=all&amp;amp;start=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-01-01&amp;amp;end=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-12-31`&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;res&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="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;API communication failed. Likely rate limited by NASA.&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;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;res&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="nf"&gt;setAllEvents&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;features&lt;/span&gt; &lt;span class="o"&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;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;NETWORK_ERR: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setIsLoading&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="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nf"&gt;fetchEvents&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="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;categories&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="c1"&gt;// Apply local categorization filtering downward to prevent network thrashing&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;let&lt;/span&gt; &lt;span class="nx"&gt;fetchedEvents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;allEvents&lt;/span&gt;&lt;span class="p"&gt;;&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;filters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fetchedEvents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fetchedEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&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;evCats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;categories&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;evCats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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="nf"&gt;setEvents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchedEvents&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="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;allEvents&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// From DisasterMap.jsx: Bounding Geometry Normalization and Fail-Safe Fallbacks&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;ev&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coordinates&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;coord&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Handle Polygon / MultiPolygon arrays smoothly to safely extract marker anchors&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;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Polygon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MultiPolygon&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;poly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coordinates&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coordinates&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coordinates&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;coord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;poly&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="nx"&gt;poly&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="c1"&gt;// Extract [lat, lng] projection values securely&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;coord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coordinates&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="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coordinates&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="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Failsafe condition to prevent React from throwing errors on unmapped coordinates&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;coord&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;isNaN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;coord&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="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;isNaN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;coord&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="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&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;Marker&lt;/span&gt; 
      &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;||&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;random&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt; 
      &lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;coord&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; 
      &lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;getIcon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;categories&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;id&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="cm"&gt;/* Dynamic Popup UI Layout */&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;/Marker&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;
  
  
  Responsive Design &amp;amp; Progressive Web App Capabilities
&lt;/h2&gt;

&lt;p&gt;Building a tool that tracks planetary events requires absolute accessibility. Disasters don't happen exclusively when you are sitting in front of a 27-inch desktop monitor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Responsive Layout Architecture
&lt;/h3&gt;

&lt;p&gt;To build an interface resilient to varying viewports, I leveraged Tailwind's responsive breakpoint layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The primary control sidebar features a flexible width layout (&lt;code&gt;w-[320px] max-w-[100vw]&lt;/code&gt;) coupled with clean, hardware-accelerated transitions (&lt;code&gt;translate-x-0&lt;/code&gt; vs &lt;code&gt;-translate-x-full&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;On smaller devices, the menu panel completely retracts with smooth CSS transitions, shifting interactive map control toggles to a dedicated corner icon trigger to preserve valuable screen real estate.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  PWA Capabilities
&lt;/h3&gt;

&lt;p&gt;I also integrated Progressive Web App capabilities into the build configuration. By writing a comprehensive web app manifest layout (&lt;code&gt;manifest.json&lt;/code&gt;), the browser recognizes the application as an independent web console app. Users can directly install the app to their local home screen on mobile devices or their desktop dock, launching it within a standalone native application frame without browser navigation wrappers.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Console Interface
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxwta6fmac0g3z5wl7upf.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%2Fxwta6fmac0g3z5wl7upf.png" alt="Main Mapping Interface with Active Cluster pins across the Map" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1: The tracking interface rendering live event telemetry. Standard leaflet markers are optimized into performant numbered groupings using react-leaflet-cluster to prevent main-thread UI blocking.&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%2Fad0hs7f9ioli9lq5ht34.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%2Fad0hs7f9ioli9lq5ht34.png" alt="Expanded Collapsible Telemetry Panel displaying Recharts Bar Charts" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 2: The Global Distribution Analytics sidebar rendering statistical summaries of volcanic, wildfire, and severe storm occurrences across the globe using interactive SVG layouts.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Engineering Review
&lt;/h2&gt;

&lt;p&gt;Developing this project across a focused engineering sprint highlighted the critical intersection of client-side performance optimization and defensive data ingestion. Initially, rendering hundreds of individual geospatial DOM nodes introduced severe main-thread lag, a critical bottleneck that I resolved by integrating &lt;code&gt;react-leaflet-cluster&lt;/code&gt; to virtualize grouped anomalies and sustain a flawless 60 FPS rendering cycle. Concurrently, navigating the volatility of public open-source telemetry streams underscored that defensive programming is non-negotiable when architecture relies on external payloads; implementing rigorous validation layers—such as checking coordinate bounds via &lt;code&gt;isNaN()&lt;/code&gt;, isolating geometry mutations, and structuring robust state fallbacks—proved essential to guarantee runtime stability and insulate the UI from catastrophic crashes caused by malformed API data.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deployments
&lt;/h2&gt;

&lt;p&gt;The application is fully operational, integrated with live automated build checks via Vercel's deployment network. Explore the implementation links below to review the codebase architecture or view live planetary indicators:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live&lt;/strong&gt; &lt;a href="https://disaster-map-nasa-eonet.vercel.app/" rel="noopener noreferrer"&gt;disaster-map-nasa-eonet.vercel.app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/SuryanshSwarn09/Disaster-map-NASA-EONET" rel="noopener noreferrer"&gt;GitHub - Disaster-map-NASA-EONET&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
      <category>react</category>
    </item>
    <item>
      <title>Stop Fighting AI Formatting: How I Built a "Sanitizer" for Messy AI Markdown</title>
      <dc:creator>Suryansh Swarn</dc:creator>
      <pubDate>Thu, 14 May 2026 17:51:39 +0000</pubDate>
      <link>https://dev.to/suryansh_swarn/stop-fighting-ai-formatting-how-i-built-a-sanitizer-for-messy-ai-markdown-3ooh</link>
      <guid>https://dev.to/suryansh_swarn/stop-fighting-ai-formatting-how-i-built-a-sanitizer-for-messy-ai-markdown-3ooh</guid>
      <description>&lt;h3&gt;
  
  
  The Problem: The "AI-to-Doc" Friction
&lt;/h3&gt;

&lt;p&gt;We’ve all been there. You ask an AI like ChatGPT, Gemini, or NotebookLM to explain a complex topic. The output is great, but when you copy-paste it into a professional document or a standard editor, it looks... broken.&lt;/p&gt;

&lt;p&gt;The biggest culprits? &lt;strong&gt;LaTeX delimiters.&lt;/strong&gt; AI tools love using &lt;code&gt;\[ ... \]&lt;/code&gt; for block math and &lt;code&gt;\( ... \)&lt;/code&gt; for inline math. Most web-based markdown parsers don’t recognize these out of the box, leaving your document littered with backslashes and brackets instead of beautiful equations.&lt;/p&gt;

&lt;p&gt;I decided to build a solution: &lt;strong&gt;Markdown Latex Pdf generator&lt;/strong&gt;. A tool to solve this "messy copy-paste" journey.&lt;/p&gt;




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

&lt;p&gt;To keep the app fast and responsive, I went with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React (Vite):&lt;/strong&gt; For the reactive UI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Marked.js:&lt;/strong&gt; For high-speed markdown parsing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;KaTeX:&lt;/strong&gt; For math rendering that actually looks like a textbook.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;html2pdf.js:&lt;/strong&gt; To turn that "Liquid Glass" UI into a portable document.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  The Engineering Challenge: The Regex "Sanitizer"
&lt;/h3&gt;

&lt;p&gt;The core "intelligence" of this app isn't just the rendering; it’s the &lt;strong&gt;pre-processing&lt;/strong&gt;. I realized that before I could hand the text over to &lt;code&gt;marked.js&lt;/code&gt;, I had to translate "AI-speak" into "Standard-Markdown."&lt;/p&gt;

&lt;p&gt;When I started building the app, I realized that simply using a markdown parser like marked.js wasn't enough. AI tools often wrap math equations in brackets that standard libraries don't recognize by default.&lt;/p&gt;

&lt;p&gt;I had to implement a custom RegEx Sanitizer to "clean" the text before it even hit the parser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Code Snippet that fixed it:&lt;/strong&gt;&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="c1"&gt;// Sanitizing AI-specific delimiters to standard LaTeX $ and $$&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sanitized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rawInput&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\\\[&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$$$$&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Convert \[ to $$&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\\\]&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$$$$&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Convert \] to $$&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\\\(&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;// Convert \( to $&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\\\)&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// Convert \) to $&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;By implementing this "middleware" logic, I ensured that no matter how the AI formats the math, my app translates it into a standard format that KaTeX and marked.js can render perfectly.&lt;/p&gt;




&lt;h3&gt;
  
  
  Aesthetic Engineering: The "Liquid Glass" UI
&lt;/h3&gt;

&lt;p&gt;As someone who bridges the gap between software utility and visual storytelling, I couldn't settle for a plain white text box. I engineered a &lt;strong&gt;"Liquid Glass"&lt;/strong&gt; aesthetic.&lt;/p&gt;

&lt;p&gt;Using modern CSS &lt;code&gt;backdrop-filter: blur()&lt;/code&gt;, fixed mesh gradients, and a sleek dark-mode-first approach, the app feels like a premium desktop tool rather than a basic web form. It provides a "zen" environment for refining AI-generated content.&lt;/p&gt;




&lt;h3&gt;
  
  
  Modern Workflow: PWA &amp;amp; Mobile Responsiveness
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fstqgwik8syz736abcnud.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%2Fstqgwik8syz736abcnud.png" alt="A wide desktop screenshot of the application interface in dark mode." width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fecxa5zk8s4kovajxd4uh.jpeg" 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%2Fecxa5zk8s4kovajxd4uh.jpeg" alt="A vertical screenshot showing the Markdown Latex Pdf web app running on a mobile device." width="800" height="1733"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F55r8o1123xu8jdlaad0v.jpeg" 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%2F55r8o1123xu8jdlaad0v.jpeg" alt="A vertical screenshot showing the Markdown Latex Pdf web app running on a mobile device." width="800" height="1733"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A productivity tool is useless if it only works on a 27-inch monitor. I focused on two key features to make this app truly "portable":&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fully Responsive Design:&lt;/strong&gt; Using a fluid grid system, the "Liquid Glass" editor scales perfectly from a desktop setup to a mobile screen. Whether you are refining an AI response on your phone or your laptop, the UI remains intuitive and clutter-free.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;PWA Capable:&lt;/strong&gt; I implemented a Web App Manifest and service worker configuration. This means you can &lt;strong&gt;"Install"&lt;/strong&gt; the app directly onto your Windows, macOS, or Android device. It lives in your dock or app drawer, launches instantly, and feels like a native system utility.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  My Journey &amp;amp; Documentation
&lt;/h3&gt;

&lt;p&gt;Building this wasn't just about the code; it was about solving a personal workflow bottleneck. I wanted a way to turn a quick AI chat into a clean PDF I could share or submit, without the formatting headache.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live Demo:&lt;/strong&gt; &lt;a href="https://markdown-pdf-self.vercel.app/" rel="noopener noreferrer"&gt;https://markdown-pdf-self.vercel.app/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/SuryanshSwarn09/markdown-pdf" rel="noopener noreferrer"&gt;SuryanshSwarn09/markdown-pdf&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

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