<?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: Reza Kheradmandi</title>
    <description>The latest articles on DEV Community by Reza Kheradmandi (@rezakh80).</description>
    <link>https://dev.to/rezakh80</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%2F3674722%2Ff31f153d-8c44-46be-b726-5736f33f1c6d.jpeg</url>
      <title>DEV Community: Reza Kheradmandi</title>
      <link>https://dev.to/rezakh80</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rezakh80"/>
    <language>en</language>
    <item>
      <title>Stop Building Backends for Simple Data Handoffs: Meet React State Warp</title>
      <dc:creator>Reza Kheradmandi</dc:creator>
      <pubDate>Sat, 03 Jan 2026 12:12:01 +0000</pubDate>
      <link>https://dev.to/rezakh80/stop-building-backends-for-simple-data-handoffs-meet-react-state-warp-4724</link>
      <guid>https://dev.to/rezakh80/stop-building-backends-for-simple-data-handoffs-meet-react-state-warp-4724</guid>
      <description>&lt;h1&gt;
  
  
  The "Cross-Device" Problem
&lt;/h1&gt;

&lt;p&gt;Have you ever been building a web application—maybe a registration form or an admin panel—and hit this specific roadblock?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The user needs to upload a photo, scan a document, or sign a canvas using their phone, but they are currently working on their desktop.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Usually, the "engineering" solution to this is surprisingly heavy:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Build an API endpoint to receive the file.&lt;/li&gt;
&lt;li&gt; Set up a database or S3 bucket to store it temporarily.&lt;/li&gt;
&lt;li&gt; Force the user to log in on their mobile device.&lt;/li&gt;
&lt;li&gt; Implement a WebSocket or Polling mechanism to update the desktop UI when the upload is done.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is a lot of infrastructure for a simple 30-second interaction. &lt;strong&gt;I wanted a better way.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So, I built &lt;strong&gt;React State Warp&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 What is React State Warp?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Reza-kh80/react-state-warp" rel="noopener noreferrer"&gt;React State Warp&lt;/a&gt; is a lightweight React Hook that creates a secure, peer-to-peer (P2P) wormhole between devices.&lt;/p&gt;

&lt;p&gt;It allows you to generate a QR code on one device (Host), scan it with another (Client), and &lt;strong&gt;instantly sync React State&lt;/strong&gt; between them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero Backend:&lt;/strong&gt; Powered by WebRTC (PeerJS). Data travels Device-to-Device.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero Database:&lt;/strong&gt; Nothing is stored on a server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instant Sync:&lt;/strong&gt; Text, JSON, and even Binary data sync in milliseconds.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🪄 The Magic: Syncing Files without a Server
&lt;/h2&gt;

&lt;p&gt;The hardest part of P2P is usually handling binary data. Most libraries break when you try to send a JavaScript &lt;code&gt;File&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;I implemented a custom serializer that automatically detects &lt;code&gt;File&lt;/code&gt;, &lt;code&gt;Blob&lt;/code&gt;, or &lt;code&gt;Uint8Array&lt;/code&gt; in your state, converts them efficiently, chunks them if necessary, and reconstructs them on the receiving device as a valid File object.&lt;/p&gt;

&lt;p&gt;This means you can do 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="c1"&gt;// 📱 On Mobile:&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"file"&lt;/span&gt; &lt;span class="na"&gt;onChange&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="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&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="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// 💻 On Desktop:&lt;/span&gt;
&lt;span class="c1"&gt;// 'data.avatar' instantly becomes a File object you can display!&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createObjectURL&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;avatar&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;h2&gt;
  
  
  🛠️ How to use it
&lt;/h2&gt;

&lt;p&gt;It is designed to be a "Headless" hook, meaning you have full control over the UI.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;react-state-warp peerjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Implement the Hook&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&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;useStateWarp&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-state-warp&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="nx"&gt;QRCode&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-qr-code&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="c1"&gt;// Initialize state like standard useState&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;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;connectionLink&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStateWarp&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="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;file&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;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="nt"&gt;div&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;"card"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Status: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Inputs are automatically synced */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; 
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
        &lt;span class="na"&gt;onChange&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="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&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="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
        &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Type here..."&lt;/span&gt; 
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Show QR Code for the other device to join */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;connectionLink&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&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;"qr-box"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;QRCode&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;connectionLink&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Scan to join!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&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;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🛡️ Handling the "Real World" (NATs &amp;amp; Firewalls)
&lt;/h2&gt;

&lt;p&gt;One of the biggest pain points with WebRTC is connecting devices that are on different networks (e.g., WiFi vs. 4G).&lt;/p&gt;

&lt;p&gt;React State Warp comes pre-configured with public Google STUN servers. This ensures that in 95% of cases, the connection punches through NATs and Firewalls automatically without you needing to configure ICE servers manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  📦 Try the Demo
&lt;/h2&gt;

&lt;p&gt;I included a complete "Identity Verification" playground in the repository. It simulates a real-world flow where a user starts a profile on Desktop and finishes verification on Mobile.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;site: &lt;a href="https://daxra.ir/docs/react-state-warp" rel="noopener noreferrer"&gt;https://daxra.ir/docs/react-state-warp&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I would love to hear your thoughts! If you find this useful or interesting, dropping a Star ⭐ on GitHub would mean the world to me.&lt;/p&gt;

&lt;p&gt;Let me know what you think in the comments below! 👇&lt;/p&gt;

&lt;h1&gt;
  
  
  react #javascript #opensource #webdev #webrtc
&lt;/h1&gt;

</description>
      <category>react</category>
      <category>opensource</category>
      <category>showdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Mastering Iranian Data Validation in Zod: From Regex to Enterprise Metadata</title>
      <dc:creator>Reza Kheradmandi</dc:creator>
      <pubDate>Tue, 23 Dec 2025 07:53:22 +0000</pubDate>
      <link>https://dev.to/rezakh80/mastering-iranian-data-validation-in-zod-from-regex-to-enterprise-metadata-5de9</link>
      <guid>https://dev.to/rezakh80/mastering-iranian-data-validation-in-zod-from-regex-to-enterprise-metadata-5de9</guid>
      <description>&lt;p&gt;If you are building a React, Next.js, or Node.js application for the Iranian market, you have definitely faced this challenge: &lt;strong&gt;Validating local data structures&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Things like &lt;strong&gt;National Code (Code Melli)&lt;/strong&gt;, &lt;strong&gt;Bank Cards&lt;/strong&gt;, &lt;strong&gt;IBAN (Sheba)&lt;/strong&gt;, and &lt;strong&gt;Postal Codes&lt;/strong&gt; follow complex algorithms (Luhn, ISO 7064, etc.).&lt;/p&gt;

&lt;p&gt;Usually, developers handle this in two ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Copy-pasting complex Regex patterns (Error-prone).&lt;/li&gt;
&lt;li&gt; Using heavy legacy libraries and manually connecting them to Zod using &lt;code&gt;refine&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Neither is ideal for a modern TypeScript stack. That's why I built &lt;strong&gt;&lt;a href="https://github.com/Reza-kh80/zod-ir" rel="noopener noreferrer"&gt;zod-ir&lt;/a&gt;&lt;/strong&gt;, which is now officially part of the &lt;strong&gt;&lt;a href="https://zod.dev/?id=ecosystem" rel="noopener noreferrer"&gt;Zod Ecosystem&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why zod-ir? (It's not just validation)
&lt;/h2&gt;

&lt;p&gt;In the latest release (v1.5.4), &lt;code&gt;zod-ir&lt;/code&gt; shifted focus from simple validation (&lt;code&gt;true/false&lt;/code&gt;) to &lt;strong&gt;Smart Data Extraction&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Imagine a form where the user enters a landline number, and you automatically detect their &lt;strong&gt;Province&lt;/strong&gt; and &lt;strong&gt;City&lt;/strong&gt;. Or they enter a card number, and you instantly show their &lt;strong&gt;Bank Logo&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Installation
&lt;/h3&gt;

&lt;p&gt;It has &lt;strong&gt;zero dependencies&lt;/strong&gt; and works as a peer dependency to Zod.&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;zod zod-ir
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. The "Smart" Validation
&lt;/h2&gt;

&lt;p&gt;Here is a real-world example of a user registration schema. Notice how clean the code is:&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;z&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;zod&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;zMelliCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;zIranianMobile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;zLandline&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;zCardNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;getLandlineInfo&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;zod-ir&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;UserSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// Validates National Code algorithm&lt;/span&gt;
  &lt;span class="na"&gt;nationalId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;zMelliCode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid National Code&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;

  &lt;span class="c1"&gt;// Validates mobile prefixes (09xx)&lt;/span&gt;
  &lt;span class="na"&gt;mobile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;zIranianMobile&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;

  &lt;span class="c1"&gt;// Validates Landline AND we can extract city later&lt;/span&gt;
  &lt;span class="na"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;zLandline&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;

  &lt;span class="c1"&gt;// Validates Card Number (Luhn)&lt;/span&gt;
  &lt;span class="na"&gt;card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;zCardNumber&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. Extracting Metadata (The Cool Part)
&lt;/h2&gt;

&lt;p&gt;Validation is boring. Let's get data!&lt;/p&gt;

&lt;p&gt;Feature A: Auto-detect City from Landline Don't ask users for their city if they provided a phone number.&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;getLandlineInfo&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;zod-ir&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;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getLandlineInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;02122334455&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cm"&gt;/* Output:
{
  province: "Tehran",
  city: "Tehran",
  province_fa: "تهران",
  city_fa: "تهران"
}
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feature B: Bank Information Get the bank name, color, and logo from a card number.&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;getBankInfo&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;zod-ir&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;bank&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getBankInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;6219861012345678&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Returns: { name: "Saman", color: "#46a0e6", logo: "..." }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Enterprise Ready?
&lt;/h2&gt;

&lt;p&gt;Yes. I designed zod-ir to address common enterprise concerns:&lt;/p&gt;

&lt;p&gt;Standalone Usage: You don't HAVE to use Zod. All validators (like isMelliCode) are exported as pure functions for backend use.&lt;/p&gt;

&lt;p&gt;Tree-Shakable: If you only import isIranianMobile, the heavy bank database won't be included in your bundle.&lt;/p&gt;

&lt;p&gt;Type-Safe: First-class TypeScript support.&lt;/p&gt;

&lt;p&gt;Conclusion&lt;br&gt;
If you are using Zod, stop writing manual regex for Iranian data. zod-ir gives you validation, transformation, and metadata extraction in one lightweight package.&lt;/p&gt;

&lt;p&gt;Give it a try and let me know what you think!&lt;/p&gt;

&lt;p&gt;🔗 site: &lt;a href="https://daxra.ir/docs/zod-ir" rel="noopener noreferrer"&gt;https://daxra.ir/docs/zod-ir&lt;/a&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>react</category>
      <category>opensource</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
