<?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: Niranjan</title>
    <description>The latest articles on DEV Community by Niranjan (@niranjan_4407).</description>
    <link>https://dev.to/niranjan_4407</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4202211%2F170ec609-8bb1-47d9-b17e-a716f369927a.png</url>
      <title>DEV Community: Niranjan</title>
      <link>https://dev.to/niranjan_4407</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/niranjan_4407"/>
    <language>en</language>
    <item>
      <title>How I built Unframer: export Framer sites to portable HTML</title>
      <dc:creator>Niranjan</dc:creator>
      <pubDate>Fri, 23 Oct 2026 09:56:59 +0000</pubDate>
      <link>https://dev.to/niranjan_4407/how-i-built-unframer-export-framer-sites-to-portable-html-36ej</link>
      <guid>https://dev.to/niranjan_4407/how-i-built-unframer-export-framer-sites-to-portable-html-36ej</guid>
      <description>&lt;p&gt;Turns a published Framer site into framework-free HTML and CSS that runs on any static host, with trackers, the React runtime and the watermark removed, and entry animations compiled to pure CSS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://unframer-dun.vercel.app" rel="noopener noreferrer"&gt;Try it live&lt;/a&gt; · &lt;a href="https://github.com/Niranjan266/unframer" rel="noopener noreferrer"&gt;Source code&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Framer sites can only live on Framer. The served HTML is already complete, so a static copy should be possible, as long as the animations survive once the runtime is gone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decisions that shaped it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Read before stripping. The declarative animation and breakpoint data is read first and compiled to CSS keyframes, and only then is the roughly 212 KB React runtime removed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Links that work everywhere. Internal links are rewritten as relative, file-explicit paths, the only form that works opened from disk, on a static host and from a subdirectory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Crawled routes are untrusted input. Path traversal, backslashes and drive letters are rejected so a link can never write outside the output folder.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Canonical URLs are retargeted with --base-url or removed, so a self-hosted copy isn't treated by search engines as a duplicate of the original.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Built with
&lt;/h2&gt;

&lt;p&gt;TypeScript, Node.js, Docker, HTML, CSS&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://niranjand.in/projects/unframer" rel="noopener noreferrer"&gt;niranjand.in&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>webdev</category>
      <category>node</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How I built EasyShare: peer-to-peer file sharing in Java</title>
      <dc:creator>Niranjan</dc:creator>
      <pubDate>Fri, 23 Oct 2026 09:50:57 +0000</pubDate>
      <link>https://dev.to/niranjan_4407/how-i-built-easyshare-peer-to-peer-file-sharing-in-java-1p46</link>
      <guid>https://dev.to/niranjan_4407/how-i-built-easyshare-peer-to-peer-file-sharing-in-java-1p46</guid>
      <description>&lt;p&gt;BitTorrent-style file sharing in plain Java with no external libraries. Files are split into pieces, every piece is SHA-1 checked, and peers download from each other in parallel while still downloading themselves.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://easyshare-p2p.vercel.app" rel="noopener noreferrer"&gt;Try it live&lt;/a&gt; · &lt;a href="https://github.com/Niranjan266/easyshare-p2p" rel="noopener noreferrer"&gt;Source code&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Move files between computers with no central file server, and prove that every byte that arrives is the byte that was sent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decisions that shaped it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Trust nothing on the wire. Every received piece is SHA-1 hashed; corrupt pieces are rejected and downloaded again. The demo makes one peer deliberately corrupt 15% of the pieces it sends, to show the check working.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Swarm with rarest-first selection, so peers share pieces while they are still downloading and no single machine becomes the bottleneck.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Three ways to find peers: a TCP tracker, LAN multicast over UDP, and a manual connect ip:port.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No dependencies beyond the JDK. Pause and resume survive restarts, and the Java program serves its own web dashboard and a phone page for devices on the same Wi-Fi.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Built with
&lt;/h2&gt;

&lt;p&gt;Java 17, TCP / UDP sockets, Multithreading, SHA-1, HTML&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://niranjand.in/projects/easyshare" rel="noopener noreferrer"&gt;niranjand.in&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>networking</category>
      <category>p2p</category>
      <category>programming</category>
    </item>
    <item>
      <title>How I built Cube Solver: camera-based Rubik's cube solver</title>
      <dc:creator>Niranjan</dc:creator>
      <pubDate>Fri, 23 Oct 2026 09:41:45 +0000</pubDate>
      <link>https://dev.to/niranjan_4407/how-i-built-cube-solver-camera-based-rubiks-cube-solver-4gc0</link>
      <guid>https://dev.to/niranjan_4407/how-i-built-cube-solver-camera-based-rubiks-cube-solver-4gc0</guid>
      <description>&lt;p&gt;Hold a Rubik's cube up to the camera and it reads each side on its own, fills in a 3D model as it goes, then walks you to solved in about 20 turns, never more than 22. Made for people who have never solved a cube.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cube.niranjand.in" rel="noopener noreferrer"&gt;Try it live&lt;/a&gt; · &lt;a href="https://github.com/Niranjan266/cube-solver" rel="noopener noreferrer"&gt;Source code&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Most solvers expect you to type in all 54 stickers and already know cube notation like R U R' U'. The goal was a solver for someone who has never solved a cube: show it the cube, then follow the arrows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decisions that shaped it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;No shutter button. The camera reads colours in the browser about ten times a second and captures a side as soon as the reading holds steady for about 0.3 seconds, in any order and held any way up. Once all six sides are in, the app works out which way up each one was held.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check the cube before solving it. The app verifies the scanned cube is physically possible. If a colour was misread it says exactly what is wrong ("one corner is twisted in place") and pulses the least-confident stickers so they can be fixed by hand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Short solutions without jargon. A built-in two-phase solver finds about 20 turns, never more than 22, played one arrow at a time on a 3D cube at Slow, Normal or Fast speed. Notation is explained only if you ask for it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Phones are a first-class layout: three screens (Scan, Check, Solve) behind a bottom tab bar, every control at least 44 px tall, and photo upload for when there is no webcam.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Built with
&lt;/h2&gt;

&lt;p&gt;Python, FastAPI, OpenCV, NumPy, SciPy, JavaScript, cubing.js&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://niranjand.in/projects/cube-solver" rel="noopener noreferrer"&gt;niranjand.in&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>computervision</category>
      <category>opencv</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How I built MetroNow Chennai: live train tracking for Chennai Metro</title>
      <dc:creator>Niranjan</dc:creator>
      <pubDate>Fri, 23 Oct 2026 09:41:09 +0000</pubDate>
      <link>https://dev.to/niranjan_4407/how-i-built-metronow-chennai-live-train-tracking-for-chennai-metro-21p7</link>
      <guid>https://dev.to/niranjan_4407/how-i-built-metronow-chennai-live-train-tracking-for-chennai-metro-21p7</guid>
      <description>&lt;p&gt;A web app that shows where every Chennai Metro train is and when it will reach your station, across all three lines and 52 stations, in English and Tamil. Built from the official timetable and anonymous rider reports, and written up as a proposal to CMRL and CUMTA and two research papers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://metronow-chennai.vercel.app" rel="noopener noreferrer"&gt;Try it live&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Chennai Metro publishes no real-time data feed, so every app, including the official one, shows only scheduled timings. A passenger can't see where the next train actually is, and a train missed by a minute costs the full gap: 3 to 7 minutes on the Blue Line at peak, 12 to 14 minutes between Alandur and St. Thomas Mount, and up to 15 to 30 minutes after 10 pm.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the research found
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No existing service shows live train positions in Chennai: not the CMRL app, not Chennai One (which tracks buses only), not Google Maps or Moovit. CMRL announced real-time timings in 2018, but the feature isn't in the current app.&lt;/li&gt;
&lt;li&gt;Disruptions leave passengers guessing. On 23–24 December 2024 a stalled train at Washermanpet stretched waits from 7 to 15–18 minutes; on 2 December 2025 passengers waited nearly 10 minutes in a tunnel between Central and High Court with no information.&lt;/li&gt;
&lt;li&gt;The official app is rated 2.3 on Google Play and 2.1 on the App Store (September 2026), with reviews mentioning removed schedules and unclear routes.&lt;/li&gt;
&lt;li&gt;Field timings matched the model: doors open 10–15 s in service (modelled 15 s), Tondiarpet to Central takes 10–15 min (modelled 10.1 min), and Wimco Nagar Depot to Airport 51–55 min (modelled 53.0 min).&lt;/li&gt;
&lt;li&gt;The work is written up as an IEEE conference paper and a longer journal manuscript on estimating arrivals without live data, with 29 references checked against the Crossref DOI registry, and the reconstructed timetable published as a GTFS feed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Decisions that shaped it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Honest by design. Every time carries a label: Scheduled (from the official timetable), Estimated (adjusted by a recent rider report) or Live (confirmed in the last two minutes). Nothing is shown as live unless it is.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rebuild the timetable from what CMRL does publish: first and last trains, and the gap between trains for peak, off-peak, late evening, Saturday and Sunday, with travel time from track distance and 15-second stops.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Riders as sensors. A tap on "arrived" or "left" moves that train to its observed position and re-times every station after it, for everyone. Reports are anonymous and deleted after 30 minutes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One data adapter for every source, shaped like GTFS-Realtime, so an official CMRL feed can replace the estimates later without changing anything passengers see.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Built for the phone in a passenger's hand: installs like an app, works offline after the first visit, a 3D map showing elevated and underground sections, and full English and Tamil.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Built with
&lt;/h2&gt;

&lt;p&gt;React, TypeScript, Vite, MapLibre GL, Three.js, Google Maps 3D, PWA, GTFS&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://niranjand.in/projects/metronow-chennai" rel="noopener noreferrer"&gt;niranjand.in&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>opendata</category>
      <category>transit</category>
      <category>research</category>
    </item>
  </channel>
</rss>
