<?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: Amit Kumar Raikwar</title>
    <description>The latest articles on DEV Community by Amit Kumar Raikwar (@amitkumarraikwar).</description>
    <link>https://dev.to/amitkumarraikwar</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%2F2469626%2Ff91d0482-371a-4c02-a66b-62fd33ae497b.jpg</url>
      <title>DEV Community: Amit Kumar Raikwar</title>
      <link>https://dev.to/amitkumarraikwar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amitkumarraikwar"/>
    <language>en</language>
    <item>
      <title>Validate and Mask Environment Variables in Node.js and TypeScript</title>
      <dc:creator>Amit Kumar Raikwar</dc:creator>
      <pubDate>Thu, 11 Jun 2026 18:38:55 +0000</pubDate>
      <link>https://dev.to/amitkumarraikwar/validate-and-mask-environment-variables-in-nodejs-and-typescript-1g9e</link>
      <guid>https://dev.to/amitkumarraikwar/validate-and-mask-environment-variables-in-nodejs-and-typescript-1g9e</guid>
      <description>&lt;p&gt;Configuring environment variables seems simple, but it frequently leads to two common issues in production-grade applications:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Missing Variables:&lt;/strong&gt; A developer adds a new variable locally but forgets to update the &lt;code&gt;.env.example&lt;/code&gt; file. Other team members pull the changes, and their local environments crash.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leaked Credentials:&lt;/strong&gt; A debug log like &lt;code&gt;console.log(process.env)&lt;/code&gt; prints database connection strings or API tokens to the terminal, leaving them visible in plaintext logs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To solve this, we created &lt;a href="https://www.npmjs.com/package/@novaedgedigitallabs/envkit" rel="noopener noreferrer"&gt;@novaedgedigitallabs/envkit&lt;/a&gt;. It is a zero-dependency (other than Zod) utility that validates, loads, and masks environment variables, and keeps your example configurations updated automatically.&lt;/p&gt;




&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Schema Validation:&lt;/strong&gt; Define your environment variables with Zod to enforce types and formats.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log Masking:&lt;/strong&gt; Automatically redact sensitive credentials in console output.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example Syncing:&lt;/strong&gt; Automatically append missing variables to your &lt;code&gt;.env.example&lt;/code&gt; file without overwriting comments or values.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Module Support:&lt;/strong&gt; Runs in ESM and CommonJS.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Getting Started
&lt;/h3&gt;

&lt;p&gt;Install the package and 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; @novaedgedigitallabs/envkit zod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Initialize your configuration in a file like &lt;code&gt;env.ts&lt;/code&gt;:&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;createEnv&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;@novaedgedigitallabs/envkit&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;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="s1"&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createEnv&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;DATABASE_URL&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="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;JWT_SECRET&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="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;PORT&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="nx"&gt;coerce&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;NODE_ENV&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="nf"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;development&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="s1"&gt;production&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="s1"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;development&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;secrets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;JWT_SECRET&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="s1"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;generateExample&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="c1"&gt;// Appends new keys to .env.example at runtime&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the variables are validated using Zod, your editor will provide full TypeScript autocomplete and type safety:&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="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;         &lt;span class="c1"&gt;// Resolved as a number&lt;/span&gt;
&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JWT_SECRET&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// Resolved as a string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Preventing Secret Leaks in Logs
&lt;/h3&gt;

&lt;p&gt;Logging environment configs is a common debugging habit. With envkit, any variables listed in the &lt;code&gt;secrets&lt;/code&gt; array are automatically masked when printed:&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="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;env&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Output:&lt;/span&gt;
&lt;span class="c1"&gt;// { &lt;/span&gt;
&lt;span class="c1"&gt;//   PORT: 3000, &lt;/span&gt;
&lt;span class="c1"&gt;//   NODE_ENV: 'development', &lt;/span&gt;
&lt;span class="c1"&gt;//   JWT_SECRET: '[MASKED]', &lt;/span&gt;
&lt;span class="c1"&gt;//   DATABASE_URL: '[MASKED]' &lt;/span&gt;
&lt;span class="c1"&gt;// }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The underlying code still accesses the correct, unmasked values when called directly (e.g., &lt;code&gt;env.JWT_SECRET&lt;/code&gt;), keeping your database connections and authentications functional while protecting your log files.&lt;/p&gt;




&lt;h3&gt;
  
  
  Keeping .env.example Files Synchronized
&lt;/h3&gt;

&lt;p&gt;Updating example files manually is tedious. Envkit offers two ways to sync them:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Runtime Syncing
&lt;/h4&gt;

&lt;p&gt;By setting &lt;code&gt;generateExample: true&lt;/code&gt; in &lt;code&gt;createEnv&lt;/code&gt;, the library reads your schema during startup and appends any missing keys directly to &lt;code&gt;.env.example&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. CLI Tool
&lt;/h4&gt;

&lt;p&gt;If you prefer to sync before running your code, you can use the CLI tool:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This parses your &lt;code&gt;.env&lt;/code&gt; file and appends only the new, missing keys to &lt;code&gt;.env.example&lt;/code&gt;. Unlike standard tools that overwrite the entire target file, this command is non-destructive: it preserves all your existing values, custom comments, and spacing.&lt;/p&gt;

&lt;p&gt;If you use non-standard file names, you can specify them manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx envkit generate &lt;span class="nt"&gt;--env&lt;/span&gt; .env.production &lt;span class="nt"&gt;--out&lt;/span&gt; .env.production.example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Comparison with Existing Tools
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;dotenv&lt;/th&gt;
&lt;th&gt;t3-env&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;envkit&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Loads env files&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zod validation&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Framework agnostic&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Secrets masking in logs&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auto &lt;code&gt;.env.example&lt;/code&gt; sync&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESM + CommonJS support&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;ESM only&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




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

&lt;p&gt;If envkit saved you time → &lt;a href="https://www.novaedgedigitallabs.tech/pay" rel="noopener noreferrer"&gt;novaedgedigitallabs.tech/pay&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Validating your environment configurations and keeping your example files updated should not require manual tracking. By integrating validation, log masking, and automated syncing, &lt;code&gt;@novaedgedigitallabs/envkit&lt;/code&gt; ensures your environment is consistent and secure.&lt;/p&gt;

&lt;p&gt;If you want to view the source code, report issues, or contribute, you can find the project on GitHub: &lt;a href="https://github.com/novaedgedigitallabs/envkit" rel="noopener noreferrer"&gt;github.com/novaedgedigitallabs/envkit&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>node</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I built a zero-dependency city search library with 50,000 cities built-in</title>
      <dc:creator>Amit Kumar Raikwar</dc:creator>
      <pubDate>Wed, 10 Jun 2026 20:29:44 +0000</pubDate>
      <link>https://dev.to/amitkumarraikwar/i-built-a-zero-dependency-city-search-library-with-50000-cities-built-in-5ek9</link>
      <guid>https://dev.to/amitkumarraikwar/i-built-a-zero-dependency-city-search-library-with-50000-cities-built-in-5ek9</guid>
      <description>&lt;p&gt;Most geo projects need city search, distance calculation, or nearest location logic at some point. The usual answer is "hit a third-party API." But that means latency, rate limits, API keys, and cost.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://www.npmjs.com/package/@novaedgedigitallabs/citykit" rel="noopener noreferrer"&gt;&lt;code&gt;@novaedgedigitallabs/citykit&lt;/code&gt;&lt;/a&gt; to solve this — a zero-dependency utility library that ships with a full dataset of &lt;strong&gt;49,992 cities across 242 countries&lt;/strong&gt;, ready to use offline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install
&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; @novaedgedigitallabs/citykit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No API key. No setup. Works in Node.js and TypeScript out of the box.&lt;/p&gt;




&lt;h2&gt;
  
  
  What it can do
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Search cities
&lt;/h3&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;search&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;@novaedgedigitallabs/citykit&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="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mumbai&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;results&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// [{ name: 'Mumbai', country: 'IN', lat: 19.0760, lng: 72.8777, ... }]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fuzzy-friendly, returns ranked matches.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Calculate distance between two cities (Haversine)
&lt;/h3&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;distance&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;@novaedgedigitallabs/citykit&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;km&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;22.7196&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;75.8577&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// Indore&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;19.0760&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;72.8777&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;  &lt;span class="c1"&gt;// Mumbai&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;km&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ~590 km&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uses the Haversine formula — accurate great-circle distance, no API needed.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Find nearest cities to a location
&lt;/h3&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;nearest&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;@novaedgedigitallabs/citykit&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;cities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;nearest&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;22.7196&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;75.8577&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Returns 5 closest cities to Indore&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great for "cities near me" features.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Filter by country, state, or continent
&lt;/h3&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;filterByCountry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filterByContinent&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;@novaedgedigitallabs/citykit&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;indianCities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;filterByCountry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;IN&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;europeanCities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;filterByContinent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;EU&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  5. Country and capital data
&lt;/h3&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;getCountry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getCapital&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;@novaedgedigitallabs/citykit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;getCountry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;IN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// { name: 'India', code: 'IN', continent: 'AS', ... }&lt;/span&gt;
&lt;span class="nf"&gt;getCapital&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;IN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// 'New Delhi'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why zero dependencies?
&lt;/h2&gt;

&lt;p&gt;Most libraries in this space pull in heavy geo packages or call external APIs. citykit bundles the dataset directly — the tradeoff is a slightly larger install size, but you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Works fully offline&lt;/li&gt;
&lt;li&gt;No rate limits&lt;/li&gt;
&lt;li&gt;No API keys to manage&lt;/li&gt;
&lt;li&gt;No latency from network calls&lt;/li&gt;
&lt;li&gt;Predictable behavior in serverless / edge environments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's also a &lt;strong&gt;lightweight variant&lt;/strong&gt; if you only need basic search without the full dataset.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real use cases I've used it for
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Autocomplete city input on a form (no API call on every keystroke)&lt;/li&gt;
&lt;li&gt;Distance filter for a property listing platform&lt;/li&gt;
&lt;li&gt;"Nearest branch" feature for a business directory&lt;/li&gt;
&lt;li&gt;Seeding a database with city/country data&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  15 functions, one import
&lt;/h2&gt;

&lt;p&gt;The full list: &lt;code&gt;search&lt;/code&gt;, &lt;code&gt;distance&lt;/code&gt;, &lt;code&gt;nearest&lt;/code&gt;, &lt;code&gt;filterByCountry&lt;/code&gt;, &lt;code&gt;filterByState&lt;/code&gt;, &lt;code&gt;filterByContinent&lt;/code&gt;, &lt;code&gt;filterByRadius&lt;/code&gt;, &lt;code&gt;getCountry&lt;/code&gt;, &lt;code&gt;getCapital&lt;/code&gt;, &lt;code&gt;getAllCountries&lt;/code&gt;, &lt;code&gt;getCitiesByPopulation&lt;/code&gt;, &lt;code&gt;getCity&lt;/code&gt;, &lt;code&gt;getContinents&lt;/code&gt;, &lt;code&gt;listCountries&lt;/code&gt;, &lt;code&gt;lightSearch&lt;/code&gt;&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;npm: &lt;a href="https://www.npmjs.com/package/@novaedgedigitallabs/citykit" rel="noopener noreferrer"&gt;npmjs.com/package/@novaedgedigitallabs/citykit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/novaedgedigitallabs/citykit" rel="noopener noreferrer"&gt;github.com/novaedgedigitallabs/citykit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;More OSS from NovaEdge: &lt;a href="https://www.novaedgedigitallabs.tech/open-source" rel="noopener noreferrer"&gt;novaedgedigitallabs.tech/open-source&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If it saves you time, consider &lt;a href="https://www.novaedgedigitallabs.tech/pay" rel="noopener noreferrer"&gt;supporting the work&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;This is v1.2.0 — actively maintained. Issues and PRs welcome.&lt;/p&gt;

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