<?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: Utkarsh Dhiman</title>
    <description>The latest articles on DEV Community by Utkarsh Dhiman (@utkarshdhiman48).</description>
    <link>https://dev.to/utkarshdhiman48</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%2F246107%2F319cf96b-d4a6-43e0-b74d-d54900b2ed0a.jpg</url>
      <title>DEV Community: Utkarsh Dhiman</title>
      <link>https://dev.to/utkarshdhiman48</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/utkarshdhiman48"/>
    <language>en</language>
    <item>
      <title>Supercharge Your Vocab Bot: Google Sheets Persistence and Better Logs</title>
      <dc:creator>Utkarsh Dhiman</dc:creator>
      <pubDate>Sat, 18 Jul 2026 00:55:00 +0000</pubDate>
      <link>https://dev.to/utkarshdhiman48/supercharge-your-vocab-bot-google-sheets-persistence-and-better-logs-3920</link>
      <guid>https://dev.to/utkarshdhiman48/supercharge-your-vocab-bot-google-sheets-persistence-and-better-logs-3920</guid>
      <description>&lt;p&gt;In our last post, we built a private Telegram bot powered by &lt;strong&gt;Gemini 2.5 Flash&lt;/strong&gt; that turns raw vocabulary words into beautiful study cards. We turned Google Apps Script into a fully functional, zero-cost cloud endpoint. If you missed that setup, you can catch up &lt;a href="https://dev.to/utkarshdhiman48/build-a-personal-vocab-boosting-telegram-bot-with-gemini-3bhc"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Right now, our bot is a great conversationalist, but it has short-term memory loss. The second you clear your chat history, your words vanish. Plus, every time you send it a word, you pay the "AI token tax"—even if you look up the exact same word three times a day.&lt;/p&gt;

&lt;p&gt;Today, we are going to fix both problems. We will extend our bot to automatically check a &lt;strong&gt;Google Sheet database&lt;/strong&gt; first to save AI tokens, save fresh words permanently, and build an automated production log tracker. Along the way, we'll peel back the curtain on how Google Cloud Platform (GCP) handles your script's architecture under the hood—and why setting up a custom GCP project fixes silent runtime crashes.&lt;br&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgf02thcfj7jx1nac028l.gif" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgf02thcfj7jx1nac028l.gif" alt="Stored words in google sheet" width="760" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the updated blueprint of our optimized system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                        [ Telegram Webhook Request ]
                                     │
                                     ▼
                   ┌──────────────────────────────────┐
                   │    Google Apps Script (GAS)      │
                   └─────────────────┬────────────────┘
                                     │
             ┌───────────────────────┴───────────────────────┐
             ▼                                               ▼
  【 OLD DEFAULT SETUP 】                         【 NEW CUSTOM GCP PROJECT 】
  • Anonymous runtime identity                    • Verified OAuth Owner Identity
  • Low-priority processing                       • High-priority processing
  • Silent write dropping                         • Bulletproof data commits
             │                                               │
             └───────────────────────┬───────────────────────┘
                                     │
                                     ▼
                      ┌──────────────────────────────┐
                      │    Step 1: Sheet Cache Check │
                      └──────────────┬───────────────┘
                                     │
                      ┌──────────────┴───────────────┐
                      │    Step 2: Gemini 2.5 API    │ (Only if not in sheet!)
                      └──────────────┬───────────────┘
                                     │
                                     ▼
                      ┌──────────────────────────────┐
                      │    Step 3: Google Sheets     │
                      └──────────────┬───────────────┘
                                     │
             ┌───────────────────────┴───────────────────────┐
             ▼                                               ▼
    [ Vocabulary Tab ]                                  [ Logs Tab ]
    • Word (A)                                          • Timestamp (A)
    • Created Time (B)                                  • Input Word (B)
    • Description (C)                                   • Status (C)
    • Sentence (D)                                      • Details/Error Trace (D)
    • Synonyms (E)                                           ▲
    • Way to Remember (F)                                    │
             │                                               │
             └───────────────[ SpreadsheetApp.flush() ]──────┘
                               Forces instant recording!


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

&lt;/div&gt;






&lt;h2&gt;
  
  
  Part 1: The Code Upgrade
&lt;/h2&gt;

&lt;p&gt;We're adding a brand new lookup and save layer in &lt;code&gt;sheet.gs&lt;/code&gt; and configuring &lt;code&gt;main.gs&lt;/code&gt; to run a "cache-first" check before burning any AI tokens.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Preparing Your Google Sheet Database
&lt;/h3&gt;

&lt;p&gt;Before writing code, create a fresh Google Sheet (type &lt;code&gt;sheets.new&lt;/code&gt; into your browser bar) and name your first tab &lt;strong&gt;&lt;code&gt;Vocabulary&lt;/code&gt;&lt;/strong&gt;. Set up your header row in Row 1 across columns A to F exactly like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Word&lt;/code&gt; | &lt;code&gt;Created Time&lt;/code&gt; | &lt;code&gt;Description&lt;/code&gt; | &lt;code&gt;Usage&lt;/code&gt; | &lt;code&gt;Synonyms&lt;/code&gt; | &lt;code&gt;Way to Remember&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Create a second tab at the bottom and name it &lt;strong&gt;&lt;code&gt;Logs&lt;/code&gt;&lt;/strong&gt;. This will act as our private production terminal window.&lt;/p&gt;

&lt;p&gt;Now, grab your unique Spreadsheet ID from your browser's URL bar (it's the long string of letters and numbers between &lt;code&gt;/d/&lt;/code&gt; and &lt;code&gt;/edit&lt;/code&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg8xvpypy3b6crj6pfodn.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg8xvpypy3b6crj6pfodn.png" alt="Showing where the URL of Spreadsheet can be found" width="800" height="154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to your Apps Script &lt;strong&gt;Project Settings&lt;/strong&gt; (Gear Icon), scroll down to &lt;strong&gt;Script Properties&lt;/strong&gt;, and add it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SPREADSHEET_ID&lt;/code&gt; ➔ &lt;em&gt;(Your copied Spreadsheet ID string)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Updating Your Code Files
&lt;/h3&gt;

&lt;p&gt;Open your workspace editor. Leave your &lt;code&gt;telegram.gs&lt;/code&gt; and &lt;code&gt;gemini.gs&lt;/code&gt; code completely as they are. Head over to the Gist link below and update the remaining files:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create &lt;code&gt;sheet.gs&lt;/code&gt;&lt;/strong&gt;: Copy the database query logic from the Gist. This handles searching through Column A to find matching records, caching data frames, and managing your execution logs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Update &lt;code&gt;main.gs&lt;/code&gt;&lt;/strong&gt;: Overwrite your existing main function with the new optimized script block. This routes traffic dynamically—loading saved entries instantly from your Google Sheet or querying Gemini when a brand new word drops.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We are keeping our code modular and clean. All the raw files we are working with today are updated and available in the gist:&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://gist.github.com/ut-01/ea1c17c671704b2a396454617911e43f" rel="noopener noreferrer"&gt;Get the Complete Updated Source Files on GitHub Gist&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Make sure you deploy a &lt;strong&gt;New Version&lt;/strong&gt; inside the deployment manager dropdown pane so the architecture update takes effect!&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 2: The Invisible Production Crash (And Why Your Logs Are Missing)
&lt;/h2&gt;

&lt;p&gt;Once you copy this code over and deploy a New Version, you might run into a frustrating rite of passage in the Apps Script world: &lt;strong&gt;The bot works fine when you click "Run" manually inside the editor, but fails silently when you message it via Telegram.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Even worse, when you check your Apps Script dashboards, the "Cloud Logs" option next to your failed production executions is grayed out or completely disabled.&lt;/p&gt;

&lt;p&gt;What gives?&lt;/p&gt;

&lt;p&gt;By default, every Apps Script runs on a hidden, micro-scoped background GCP project managed entirely by Google. Because you don't own that background container, Google strips away your administrative logging privileges. When an anonymous webhook executes via Telegram, it runs on low-priority infrastructure. If it runs out of processing breath, it dies mid-flight—and your cached spreadsheet writes (&lt;code&gt;appendRow&lt;/code&gt;) vanish into thin air.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 3: The GCP Architecture Explained (Simply)
&lt;/h2&gt;

&lt;p&gt;To make our bot bulletproof, we need to connect it to our own &lt;strong&gt;Standard GCP Project&lt;/strong&gt; and configure an OAuth Consent Screen. Let's break down exactly what that means.&lt;/p&gt;

&lt;p&gt;Think of a Google Cloud Project as a secure &lt;strong&gt;Digital Office Building&lt;/strong&gt; that you own. Inside this building, different specialized departments work together.&lt;/p&gt;

&lt;p&gt;When our bot runs inside your custom GCP project building, the flow changes completely:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Front Gate (Telegram Webhook):&lt;/strong&gt; Telegram hits your &lt;code&gt;doPost&lt;/code&gt; URL endpoint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Security Desk (OAuth Consent Screen):&lt;/strong&gt; Because you set up an OAuth profile, your script isn't running as an anonymous internet stranger anymore. It holds a verified digital security badge. It inherits permissions seamlessly via &lt;strong&gt;Implicit Scopes&lt;/strong&gt;—meaning Apps Script pre-scanned your code, realized you were touching Sheets, and automatically authorized your badge to read/write to your spreadsheet file as &lt;em&gt;you&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High-Priority Execution:&lt;/strong&gt; Because you own the building, Google allocates a dedicated, high-priority processing runtime. Your script gets the server bandwidth it needs to safely check your sheet cache, talk to Gemini if needed, and drop the data straight into your spreadsheet grids.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Security Cameras (Cloud Logging Explorer):&lt;/strong&gt; Every single print statement and error stack trace is permanently caught on camera. Because you are the building administrator, you can open the &lt;strong&gt;Log Explorer&lt;/strong&gt; dashboard anytime to review production behaviors.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 4: Connecting Your Script to Your GCP Project
&lt;/h2&gt;

&lt;p&gt;Ready to make your bot production-grade? Follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Head over to the &lt;a href="https://console.cloud.google.com/" rel="noopener noreferrer"&gt;Google Cloud Console&lt;/a&gt; and create a new project.&lt;/li&gt;
&lt;li&gt;Search for &lt;strong&gt;OAuth Consent Screen&lt;/strong&gt; in the top bar, set User Type to &lt;strong&gt;External&lt;/strong&gt;, and fill out the basic app name and your email (you can leave scopes completely blank—Apps Script's implicit scopes will handle that on deployment!).&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Project Settings&lt;/strong&gt; in the GCP dashboard and copy your &lt;strong&gt;Project Number&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Return to your Apps Script editor, click the gear icon (&lt;strong&gt;Project Settings&lt;/strong&gt;), click &lt;strong&gt;Change project&lt;/strong&gt;, and paste your Project Number.&lt;/li&gt;
&lt;/ol&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fopkmv6s7unrslley4vlo.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fopkmv6s7unrslley4vlo.png" alt="Screenshot showing the " width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;While you are in your Apps Script Project Settings, make sure to check the box labeled &lt;strong&gt;"Log uncaught exceptions to Cloud Operations"&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Deploy a &lt;strong&gt;New Version&lt;/strong&gt; of your Web App one last time (&lt;strong&gt;Deploy &amp;gt; Manage Deployments &amp;gt; Edit &amp;gt; New Version &amp;gt; Deploy&lt;/strong&gt;).&lt;/p&gt;




&lt;h2&gt;
  
  
  The Verdict
&lt;/h2&gt;

&lt;p&gt;Go back to Telegram and send your bot a word you already looked up. It will reply almost instantly, stamped with appropriate marker.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjudc01r5hnkolt8ld65o.gif" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjudc01r5hnkolt8ld65o.gif" alt="Final resulted bot" width="800" height="827"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Send it a completely new word, and you will watch it slide into your &lt;code&gt;Vocabulary&lt;/code&gt; spreadsheet in real time, with an execution confirmation flag stamped cleanly in your &lt;code&gt;Logs&lt;/code&gt; tab.&lt;/p&gt;

&lt;p&gt;You now have an incredibly optimized, AI-powered vocabulary engine that tracks your learning database for life without wasting API credits.&lt;/p&gt;

&lt;p&gt;Drop a comment below if your token-saving sheet integration is humming along perfectly, and happy hacking! 🚀&lt;/p&gt;

</description>
      <category>googlecloud</category>
      <category>telegram</category>
      <category>logging</category>
      <category>ai</category>
    </item>
    <item>
      <title>How to Set Up Absolute Imports in Node.js and TypeScript with Nodemon</title>
      <dc:creator>Utkarsh Dhiman</dc:creator>
      <pubDate>Fri, 17 Jul 2026 11:12:50 +0000</pubDate>
      <link>https://dev.to/utkarshdhiman48/how-to-set-up-absolute-imports-in-nodejs-and-typescript-with-nodemon-2lo1</link>
      <guid>https://dev.to/utkarshdhiman48/how-to-set-up-absolute-imports-in-nodejs-and-typescript-with-nodemon-2lo1</guid>
      <description>&lt;h3&gt;
  
  
  TLDR
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Switching from relative to absolute imports in TypeScript can greatly enhance code readability and manageability. By updating the &lt;code&gt;tsconfig.json&lt;/code&gt; settings to use a fixed path from your project's root, you can simplify import statements. Additionally, when using nodemon and ts-node for development with absolute imports, you need to install &lt;code&gt;tsconfig-paths&lt;/code&gt; and configure it in &lt;code&gt;tsconfig.json&lt;/code&gt;. Updating these configurations ensures smooth functioning of absolute imports in your TypeScript project.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I was working on a TypeScript project when I noticed messy relative imports. I'm sure you too may have stumbled across something like this. Relative imports make our code verbose and hard to understand where things are coming from, especially when files are nested in folders. For every relative import I write, I have to calculate the number of dots and slashes from the current file.&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="c1"&gt;// example of relative imports&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;validateUser&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;../../models/user&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;cors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;middleware&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;../../middlewares&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;connectDb&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;../../db&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;p&gt;Absolute imports to the rescue, they make your code cleaner and easier to manage by letting you use a fixed path from the root of your project instead of complex relative paths. This improves readability, and avoids confusion from navigating nested directories. For instance:&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="c1"&gt;// example of absolute imports&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;validateUser&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;@/models/user&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;cors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;middleware&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;@/middlewares&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;connectDb&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;@/db&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;p&gt;To switch from relative to absolute imports, make sure your &lt;code&gt;tsconfig.json&lt;/code&gt; has these configurations set to appropriate values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tsconfig.json&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"es2016"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"commonjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;configurations&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;absolute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;imports&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"rootDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"baseUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@/*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"./src/*"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nl"&gt;"esModuleInterop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"forceConsistentCasingInFileNames"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"skipLibCheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, since we use &lt;code&gt;nodemon&lt;/code&gt; for hot module reloading on the development server, it needs &lt;code&gt;ts-node&lt;/code&gt;, a TypeScript compiler, to work. This setup works perfectly with relative imports. However, with absolute imports, we need to install another development dependency and add some configuration to &lt;code&gt;tsconfig.json&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# install this package as development dependency&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; tsconfig-paths
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tsconfig.json(final)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"es2016"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"commonjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"rootDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"baseUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"@/*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"./src/*"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"esModuleInterop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"forceConsistentCasingInFileNames"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"skipLibCheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;This&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;registers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;TypeScript&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;resolver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;which&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;enables&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;resolution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;TypeScript&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;paths.&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ts-node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"require"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"tsconfig-paths/register"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if we run the project in development using &lt;code&gt;nodemon&lt;/code&gt;, absolute imports work just fine. Here's an example of how the &lt;code&gt;scripts&lt;/code&gt; section in &lt;code&gt;package.json&lt;/code&gt; looks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;  
&lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nodemon ./src/index.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm using &lt;code&gt;tsc&lt;/code&gt; for production build and &lt;code&gt;ts-node&lt;/code&gt; for development server through &lt;code&gt;nodemon&lt;/code&gt;. Deciding between &lt;code&gt;tsc&lt;/code&gt; and &lt;code&gt;ts-node&lt;/code&gt; requires understanding how they work internally and what purpose they serve. To learn more about it, &lt;a href="https://hatchjs.com/ts-node-vs-tsc/" rel="noopener noreferrer"&gt;read here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>node</category>
      <category>express</category>
      <category>typescript</category>
      <category>nodemon</category>
    </item>
    <item>
      <title>Build a Personal Vocab-Boosting Telegram Bot with Gemini</title>
      <dc:creator>Utkarsh Dhiman</dc:creator>
      <pubDate>Thu, 16 Jul 2026 10:16:35 +0000</pubDate>
      <link>https://dev.to/utkarshdhiman48/build-a-personal-vocab-boosting-telegram-bot-with-gemini-3bhc</link>
      <guid>https://dev.to/utkarshdhiman48/build-a-personal-vocab-boosting-telegram-bot-with-gemini-3bhc</guid>
      <description>&lt;p&gt;Ever come across a word like &lt;em&gt;serendipity&lt;/em&gt; or &lt;em&gt;valiancy&lt;/em&gt; and thought, &lt;em&gt;"I should write that down,"&lt;/em&gt; only to completely forget about it five minutes later?&lt;/p&gt;

&lt;p&gt;Yeah, me too.&lt;/p&gt;

&lt;p&gt;Instead of carrying around a leather notebook like a 19th-century poet, let's build a private Telegram bot that does the heavy lifting for us. You send it a raw word or phrase, it runs it through Google’s lightning-fast &lt;strong&gt;Gemini 2.5 Flash&lt;/strong&gt; model, and spits back a beautifully formatted dictionary card with the definition, synonyms, a custom mnemonic device, and an example sentence. Plus, you get a complete journal in Google Sheets (which we'll cover in the next blog post!).&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frjzblj8rivh78w0payh5.gif" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frjzblj8rivh78w0payh5.gif" alt="Working example of telegram bot" width="800" height="827"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Best part? It’s completely free, requires zero server maintenance, and takes about 15 minutes.&lt;/p&gt;

&lt;p&gt;Here is the high-level blueprint of what we're building today:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       ┌───────────┐
       │ Your Phone│
       └─────┬─────┘
             │
             │ 1. Send word (e.g., "Serendipity")
             ▼
   ┌───────────────────┐
   │  Telegram Bot     │
   └─────────┬─────────┘
             │
             │ 2. Webhook HTTPS POST
             ▼
┌─────────────────────────┐
│ Google Apps Script (GAS)│ ◄─── Check: Is CHAT_ID == Owner?
└────────────┬────────────┘
             │
             │ 3. Forward prompt with strict JSON schema
             ▼
     ┌───────────────┐
     │  Gemini AI    │  (gemini-2.5-flash)
     └───────┬───────┘
             │
             │ 4. Return clean, structured JSON object
             ▼
┌─────────────────────────┐
│ Google Apps Script (GAS)│
└────────────┬────────────┘
             │
             │ 5. Parse JSON &amp;amp; format beautiful HTML template
             ▼
   ┌───────────────────┐
   │  Telegram Bot     │
   └─────────┬─────────┘
             │
             │ 6. Drop study card in your chat box!
             ▼
       ┌───────────┐
       │ Your Phone│
       └───────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Secret Sauce: Demystifying Apps Script as a Free Cloud Function Engine
&lt;/h2&gt;

&lt;p&gt;Normally, building an automation backend or conversational bot means provisioning an AWS EC2 instance, setting up a Node.js Express server, managing API gateways, and worrying about environment configurations. If you look into traditional serverless infrastructure like AWS Lambda or GCP Cloud Functions, you still have to deal with deployment pipelines, IAM roles, and credit card billing setups.&lt;/p&gt;

&lt;p&gt;We aren't doing any of that.&lt;br&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjsepcwhv8mx8z6sdeql5.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjsepcwhv8mx8z6sdeql5.png" alt="We don't do that here" width="300" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead, we are leveraging &lt;strong&gt;Google Apps Script (GAS)&lt;/strong&gt;. Most people think Apps Script is just for writing macro shortcuts inside Google Sheets, but it is actually a fully-fledged, serverless &lt;strong&gt;Cloud Function runtime&lt;/strong&gt; hidden in plain sight.&lt;/p&gt;

&lt;p&gt;When we deploy code as a Web App in GAS, Google instantly handles the deployment pipeline, provisions a public HTTPS endpoint, opens up a security layer, and listens for webhooks out of the box. Telegram pings our Apps Script cloud endpoint via a webhook, Google wakes our script up to process the incoming payload, and then it turns it back off. Total infrastructure cost: &lt;strong&gt;$0.00&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let’s dive into the setup.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 1: Secure Your API Tokens (The Setup Phase)
&lt;/h2&gt;

&lt;p&gt;Before writing any code, we need our digital access keys. We need to collect exactly three things: a Telegram bot token, your private user ID, and a Google Gemini API key.&lt;/p&gt;
&lt;h3&gt;
  
  
  A. Create Your Bot via BotFather
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Click this link to open the official Telegram bot manager: &lt;a href="https://telegram.me/BotFather" rel="noopener noreferrer"&gt;telegram.me/BotFather&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Send the message &lt;code&gt;/newbot&lt;/code&gt; to start the setup.&lt;/li&gt;
&lt;li&gt;Give your bot a friendly display name (e.g., &lt;code&gt;My Vocab Journal Bot&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Give your bot a unique username ending in the word &lt;code&gt;bot&lt;/code&gt; (e.g., &lt;code&gt;my_vocab_helper_bot&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copy the long HTTP API token string&lt;/strong&gt; it gives you. Keep this secret!&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  B. Extract Your Private Chat ID
&lt;/h3&gt;

&lt;p&gt;Because we don't want strangers using our cloud bot server and burning our free AI credits, we need to lock the application down to your personal account profile.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click this link to chat with a simple ID extractor bot: &lt;a href="https://telegram.me/userinfobot" rel="noopener noreferrer"&gt;telegram.me/userinfobot&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Press &lt;strong&gt;Start&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Copy the numeric &lt;strong&gt;&lt;code&gt;Id&lt;/code&gt;&lt;/strong&gt; string it prints out immediately (e.g., &lt;code&gt;123456789&lt;/code&gt;). This is your unique &lt;code&gt;CHAT_ID&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  C. Create a Free Gemini API Key
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Head over to the &lt;a href="https://aistudio.google.com/" rel="noopener noreferrer"&gt;Google AI Studio Console&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Log in with your standard Google account.&lt;/li&gt;
&lt;li&gt;Click the prominent &lt;strong&gt;Get API Key&lt;/strong&gt; button.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create API Key&lt;/strong&gt;, select your project container, and copy the generated alphanumeric key string.&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  Step 2: Setting up the Google Apps Script Space
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Head over to &lt;a href="https://script.google.com" rel="noopener noreferrer"&gt;script.google.com&lt;/a&gt; and click &lt;strong&gt;New Project&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Rename the project to something descriptive, like &lt;code&gt;Gemini Vocab Bot&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Before dropping code files in, click on the gear icon (&lt;strong&gt;Project Settings&lt;/strong&gt;) on the left sidebar menu drawer.&lt;/li&gt;
&lt;/ol&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo5krnmos28gce8opbrbt.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo5krnmos28gce8opbrbt.png" alt="Screenshot highlighting the gear icon on the left navigation panel for Project Settings inside Google Apps Script" width="758" height="717"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Scroll all the way down to the bottom section titled &lt;strong&gt;Script Properties&lt;/strong&gt;. This is Google's built-in secure vault for storing your private environment variables.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Add script property&lt;/strong&gt; three times and save these exact key-value pairs:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;TELEGRAM_BOT_TOKEN&lt;/code&gt; ➔ &lt;em&gt;(Your copied Telegram token)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GOOGLE_API_KEY&lt;/code&gt; ➔ &lt;em&gt;(Your copied Gemini API key)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;CHAT_ID&lt;/code&gt; ➔ &lt;em&gt;(Your numeric private Chat ID string)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;Save script properties&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  Step 3: Getting the Code
&lt;/h2&gt;

&lt;p&gt;We want to keep this architecture simple and modular. On the left sidebar menu, click the &lt;strong&gt;Editor&lt;/strong&gt; icon (the &lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt; symbol). You will see a single file named &lt;code&gt;Code.gs&lt;/code&gt;. Rename it to &lt;code&gt;main.gs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then, create two more files by clicking the &lt;strong&gt;&lt;code&gt;+&lt;/code&gt;&lt;/strong&gt; icon next to Files, choosing &lt;strong&gt;Script&lt;/strong&gt;, and naming them &lt;code&gt;gemini&lt;/code&gt; and &lt;code&gt;telegram&lt;/code&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkywdf41nb4vduqg9wgli.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkywdf41nb4vduqg9wgli.png" alt="Visual highlighting the small '+' plus icon button next to the Files sidebar heading to create clean script tabs" width="578" height="888"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All three files are available in this GitHub Gist. &lt;br&gt;
From this embedded Gist copy the logic into your workspace files matching each filename:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copy &lt;code&gt;gemini.gs&lt;/code&gt; to enforce a strict structured output schema so Gemini's responses never break your layouts.&lt;/li&gt;
&lt;li&gt;Copy &lt;code&gt;telegram.gs&lt;/code&gt; to drive raw HTML text formatting delivery frames directly into chat panels.&lt;/li&gt;
&lt;li&gt;Copy &lt;code&gt;main.gs&lt;/code&gt; to act as the primary webhook controller, verifying security gates and organizing traffic patterns.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 4: Hooking It Up to Telegram (Deploy &amp;amp; Webhook)
&lt;/h2&gt;

&lt;p&gt;Now for the final step: publishing your code as a live microservice and telling Telegram where to forward incoming chat messages.&lt;/p&gt;

&lt;h3&gt;
  
  
  A. Deploying the Script Web App
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Click the blue &lt;strong&gt;Deploy&lt;/strong&gt; button in the top right corner, then select &lt;strong&gt;New Deployment&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click the gear icon next to "Select type" and choose &lt;strong&gt;Web App&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Fill out the deployment configuration fields:&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execute as:&lt;/strong&gt; Select &lt;strong&gt;Me (your email address)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Who has access:&lt;/strong&gt; Select strictly &lt;strong&gt;Anyone&lt;/strong&gt;. &lt;em&gt;(Telegram needs public webhook access to safely hit this API).&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;Deploy&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  B. Bypassing the Developer Security Warning Screen
&lt;/h3&gt;

&lt;p&gt;Because our custom script interacts with external networks (Telegram and Gemini), Google prompts a standard safety check sequence since it is an unverified independent development workspace. &lt;strong&gt;Don't worry—this is expected behaviour for your custom tools.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flfijxi3kyy6zn0ooscib.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flfijxi3kyy6zn0ooscib.jpeg" alt="Screenshot pointing out the small gray 'Advanced' link at the bottom left text block of the Google login security screen" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When the authorization window prompts you, click &lt;strong&gt;Review Permissions&lt;/strong&gt; and select your active email profile.&lt;/li&gt;
&lt;li&gt;On the screen that reads &lt;em&gt;"Google hasn’t verified this app"&lt;/em&gt;, click the tiny gray &lt;strong&gt;Advanced&lt;/strong&gt; text link located at the bottom left.&lt;/li&gt;
&lt;li&gt;Click the sub-link that appears below it: &lt;strong&gt;Go to Gemini Vocab Bot (unsafe)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Allow&lt;/strong&gt; to finalize your live environment.&lt;/li&gt;
&lt;li&gt;Copy the long production &lt;strong&gt;Web App URL&lt;/strong&gt; it generates (it will end in &lt;code&gt;/exec&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  C. Binding the Telegram Webhook
&lt;/h3&gt;

&lt;p&gt;To hook your bot up to this new endpoint, open a fresh tab in your web browser, paste this URL format into your address bar (replacing the bracketed placeholders with your real values):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://api.telegram.org/bot&amp;lt;YOUR_TELEGRAM_BOT_TOKEN&amp;gt;/setWebhook?url=&amp;lt;YOUR_APPS_SCRIPT_WEB_APP_URL&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure your URL doesn't contain any spaces or placeholder symbols. Your URL should look like: &lt;code&gt;https://api.telegram.org/bot823499087:AAH_n4XxMg5LsdQ6XwGIrGDGf-4ryee7Haw/setWebhook?url=https://script.google.com/macros/s/AKfoyAJHafe28QP3iqV9-XjhQbnsiouf7243lonTItn_eXTlcxdfJofyUOkXxN_mKfefh12XjT2yKdBmEK/exec&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Press Enter&lt;/p&gt;

&lt;p&gt;If your screen returns a success message confirming &lt;code&gt;{"ok":true,"result":true,"description":"Webhook was set"}&lt;/code&gt;, your cloud microservice is officially linked! &lt;/p&gt;




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

&lt;p&gt;Open up Telegram, pull up your brand new personal bot thread, and send it a word like &lt;em&gt;unprecedented&lt;/em&gt;. Within a couple of seconds, you’ll get a perfectly structured, beautifully formatted study card delivered right to your pocket!&lt;/p&gt;

&lt;p&gt;Stay tuned—in the next post, I'll show you how to expand this serverless architecture by automatically caching lookups to save AI tokens, and mapping these words into a permanent, beautiful database using Google Sheets.&lt;/p&gt;

&lt;p&gt;Drop a comment below if your bot is live! 🚀&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>ai</category>
      <category>telegram</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Custom Frontend for Google Form</title>
      <dc:creator>Utkarsh Dhiman</dc:creator>
      <pubDate>Sat, 30 Jan 2021 12:28:15 +0000</pubDate>
      <link>https://dev.to/utkarshdhiman48/custom-frontend-for-google-form-456l</link>
      <guid>https://dev.to/utkarshdhiman48/custom-frontend-for-google-form-456l</guid>
      <description>&lt;p&gt;Google form is one of the easiest ways to collect data. The collected data is preorganized and can be analyzed using various tools and add-ons.&lt;/p&gt;

&lt;h4&gt;
  
  
  Prequisite
&lt;/h4&gt;

&lt;p&gt;You should be familiar with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form" rel="noopener noreferrer"&gt;HTML forms&lt;/a&gt; at least. Having knowledge of JavaScript and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch" rel="noopener noreferrer"&gt;fetch API&lt;/a&gt; will be great.&lt;/p&gt;

&lt;h3&gt;
  
  
  Need of custom front-end
&lt;/h3&gt;

&lt;p&gt;There may be cases when you need a consistent design for your website. Although you can always create your form with a server and database but embedding Google form in your website can be much easier and economical.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Implementation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The very first requirement is to turn off the 'Require sign-in' sub-options in form settings.&lt;br&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%2Fi%2F5ehljhd5x7wj7x2ss8fp.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5ehljhd5x7wj7x2ss8fp.JPG" alt="Google Form settings" width="583" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open your Google Form using the sharable link to extract the necessary information, it can be tricky at times.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Browser DevTools (F12 or Ctrl+Shift+i for chrome)&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extracting Form Action URL&lt;br&gt;
search for &lt;code&gt;&amp;lt;form&lt;/code&gt;&lt;br&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%2Fi%2Fxm7zp3vjzy2hf7gdu5jm.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxm7zp3vjzy2hf7gdu5jm.JPG" alt="Extracting action URL" width="800" height="571"&gt;&lt;/a&gt;&lt;br&gt;
get the &lt;code&gt;action&lt;/code&gt; attribute of form. It looks like &lt;a href="https://docs.google.com/forms/u/0/d/e/1FAIpQLSfAnJAbfTl23gNM6gAbU1gAXo03N9I6pf5LJbo3Ptmex5nqUg/formResponse" rel="noopener noreferrer"&gt;https://docs.google.com/forms/u/0/d/e/1FAIpQLSfAnJAbfTl23gNM6gAbU1gAXo03N9I6pf5LJbo3Ptmex5nqUg/formResponse&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extracting &lt;code&gt;name&lt;/code&gt; attribute(s)&lt;br&gt;
Search for &lt;code&gt;&amp;lt;input&lt;/code&gt; in DevTools, you may find many input fields look for the one that looks like this. &lt;code&gt;entry.294341084&lt;/code&gt;&lt;br&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%2Fi%2Fovd3afl5bivi8oe5iqun.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fovd3afl5bivi8oe5iqun.JPG" alt="Extracting name attributes" width="800" height="571"&gt;&lt;/a&gt;&lt;br&gt;
Input fields for inputs like radio button etc. are not present initially you have to select any option which will create a corresponding hidden input element otherwise, simply remove the &lt;code&gt;\_sentinel&lt;/code&gt; form &lt;code&gt;entry.100000084\_sentinel&lt;/code&gt; without checking radio button.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Custom front-end can be created in either of the following ways.
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Only HTML forms&lt;/strong&gt;: Easy way&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fetch API + HTML forms&lt;/strong&gt;: Better way&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Only HTML form
&lt;/h4&gt;

&lt;p&gt;Create an HTML form, set its &lt;code&gt;action&lt;/code&gt; attribute to previously extracted &lt;code&gt;action URL&lt;/code&gt; and &lt;code&gt;method&lt;/code&gt; attribute should be &lt;code&gt;POST&lt;/code&gt;.&lt;br&gt;
Set &lt;code&gt;name&lt;/code&gt; attributes to corresponding input(s).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"form"&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"https://docs.google.com/forms/d/e/1FAIpQLSfAnJAbfTl23gNM6gAbU1gAXo03N9I6pf5LJbo3Ptmex5nqUg/formResponse"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"inp1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Write something&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"entry.294341084"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"inp1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it add CSS to make it beautiful.&lt;br&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%2Fi%2Fdlpuwrhv8soj9ktrvulz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdlpuwrhv8soj9ktrvulz.jpg" alt="With css" width="800" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this approach, on submission, you will be redirected to the Google Forms acknowledgment page. -_- not so cool. You can avoid this by using fetch API.&lt;/p&gt;
&lt;h4&gt;
  
  
  Fetch API + HTML form
&lt;/h4&gt;

&lt;p&gt;Create a Form, can be same as above. Prevent default behaviour of form so as to use fetch API using javascript. You have to set Method to post, the header should be &lt;code&gt;"Content-Type": "application/json"&lt;/code&gt;. You may or may not set &lt;code&gt;mode&lt;/code&gt; to &lt;code&gt;no-cors&lt;/code&gt; it will throw an error on &lt;code&gt;cors&lt;/code&gt; mode but will work anyway.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://docs.google.com/forms/d/e/1FAIpQLSfAnJAbfTl23gNM6gAbU1gAXo03N9I6pf5LJbo3Ptmex5nqUg/formResponse&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//action url&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#form&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//form element&lt;/span&gt;

&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&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="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="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="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="c1"&gt;//prevent default behaviour&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="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;no-cors&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&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;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;getInputData&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&amp;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;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Form Submitted&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="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="o"&gt;=&amp;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="c1"&gt;//promise based&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;//populating input data&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getInputData&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;dataToPost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;//formdata API&lt;/span&gt;

    &lt;span class="c1"&gt;//fill name attributes to corresponding values&lt;/span&gt;
    &lt;span class="nx"&gt;dataToPost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;entry.294341084&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#inp1&lt;/span&gt;&lt;span class="dl"&gt;"&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dataToPost&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The response from fetch &lt;code&gt;post&lt;/code&gt; request is not satisfactory, but it doesn't matter since it works. ;P&lt;br&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%2Fi%2Fvrn86w0m1iupq0tc3bb1.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvrn86w0m1iupq0tc3bb1.JPG" alt="fetch api response" width="570" height="39"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The advantage of using this approach over HTML forms is you have full control, the user won't be redirected to Google Form's acknowledgement page.&lt;/p&gt;

&lt;p&gt;Checkout a working example here.&lt;br&gt;
&lt;iframe src="https://jsfiddle.net/utkarsh48/bgc0fhs5//embedded/result,js,html,css//dark" width="100%" height="600"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Considerations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Custom Front End for the google forms can only be used to collect data.&lt;/li&gt;
&lt;li&gt;  It will work only if ‘Require Sign-In’ is turned off in Google form settings.&lt;/li&gt;
&lt;li&gt;  For Radio buttons, checkboxes etc. only exact values will be accepted, even a small spelling mistake will discard the answer for that particular question.&lt;/li&gt;
&lt;li&gt;  Tricky and Time-Consuming&lt;/li&gt;
&lt;li&gt;  Partial Response by the user if not handled properly, so frontend design should also validate user responses.&lt;/li&gt;
&lt;li&gt;  Sections in google form can be submitted by a single &lt;code&gt;post&lt;/code&gt; request.&lt;/li&gt;
&lt;li&gt;  Images can also be posted using this approach.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It may be a time-consuming task to create a custom frontend for a google form, but results can be worth the effort.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>html</category>
      <category>frontend</category>
      <category>googleform</category>
    </item>
    <item>
      <title>Regular Expressions - not so regular!</title>
      <dc:creator>Utkarsh Dhiman</dc:creator>
      <pubDate>Sun, 17 May 2020 15:13:16 +0000</pubDate>
      <link>https://dev.to/utkarshdhiman48/regular-expressions-not-so-regular-2m9p</link>
      <guid>https://dev.to/utkarshdhiman48/regular-expressions-not-so-regular-2m9p</guid>
      <description>&lt;h3&gt;
  
  
  Table Of Contents
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Modifiers (or flags)&lt;/li&gt;
&lt;li&gt;Brackets&lt;/li&gt;
&lt;li&gt;Meta Characters&lt;/li&gt;
&lt;li&gt;Quantifiers&lt;/li&gt;
&lt;li&gt;Miscellaneous&lt;/li&gt;
&lt;li&gt;Real World applications&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Regular Expressions aka RegEx. or RegExp. are powerful tools widely used for pattern matching within strings. They are supported by almost all programming languages. However choice of language plays a key role in deciding the usage and syntax of the same. Here, I'll be using JavaScript. A Website &lt;a href="https://regex101.com" rel="noopener noreferrer"&gt;regex101&lt;/a&gt; will let you use regular expressions even without the knowledge of programming language.&lt;/p&gt;

&lt;h3&gt;
  
  
  What does it look like?
&lt;/h3&gt;

&lt;p&gt;&lt;iframe src="https://jsfiddle.net/utkarsh48/d01mxacu//embedded/js//dark" width="100%" height="600"&gt;
&lt;/iframe&gt;
&lt;br&gt;
This code will make sense as you proceed further.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to use regular expressions
&lt;/h2&gt;

&lt;p&gt;It depends majorly upon the language. In JavaScript there are various functions for the same eg: &lt;code&gt;match()&lt;/code&gt;, &lt;code&gt;test()&lt;/code&gt; and &lt;code&gt;search()&lt;/code&gt; are widely used. In MySQL keyword &lt;code&gt;LIKE&lt;/code&gt;, &lt;code&gt;REGEXP&lt;/code&gt; or operator &lt;code&gt;~&lt;/code&gt; (aka post-fix operator) are used for searching.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://jsfiddle.net/utkarsh48/uhzk8gL4//embedded/js,result//dark" width="100%" height="600"&gt;
&lt;/iframe&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%2Fl0tnqom5yzptfjnic10s.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%2Fl0tnqom5yzptfjnic10s.jpeg" alt="A meme" width="616" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
Kneel before the god ;P by &lt;a href="https://memegenerator.com" rel="noopener noreferrer"&gt;memegenerator&lt;/a&gt;



&lt;h2&gt;
  
  
  Regular Expressions usually have
&lt;/h2&gt;

&lt;p&gt;Quantifiers, Operators, Modifiers (or Flags).&lt;/p&gt;

&lt;h3&gt;
  
  
  Modifiers &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;Modifier&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;'g'&lt;/td&gt;
&lt;td&gt;for global search i.e. It won't stop searching after first match and will return all the matches.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;'i'&lt;/td&gt;
&lt;td&gt;for case in-sensitive search&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;'m'&lt;/td&gt;
&lt;td&gt;for multi-line search (the regexp should be surrounded by ^ and $)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Brackets&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;Brackets&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[abc]&lt;/td&gt;
&lt;td&gt;look for any one character between the square brackets(like an OR operator in programming languages)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[a-z]&lt;/td&gt;
&lt;td&gt;includes all lower-case alphabets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[A-Z]&lt;/td&gt;
&lt;td&gt;includes all upper-case alphabets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[A-z]&lt;/td&gt;
&lt;td&gt;includes both upper-case and lower-case alphabets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[0-9]&lt;/td&gt;
&lt;td&gt;includes all numerals&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[^abc]&lt;/td&gt;
&lt;td&gt;Will look for everything other than a,b,c (^ represents inverse here only in square-brackets otherwise it represent anchor operator)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(p|q)&lt;/td&gt;
&lt;td&gt;It is known as grouping operator, it divides the expression within sub-groups. It also saves the index of subgroup starting from 1-9 (which is used by back-reference operator)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Meta characters&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
    &lt;th&gt;Meta-character&lt;/th&gt;
    &lt;th&gt;Description&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;.&lt;/td&gt;
    &lt;td&gt;Finds a single character, except newline or line terminator&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;\w&lt;/td&gt;
    &lt;td&gt;Finds a word character it include [A-Za-z0-9_]&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;\W&lt;/td&gt;
    &lt;td&gt;Finds a non-word character&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;\d&lt;/td&gt;
    &lt;td&gt;Finds a digit&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;\D&lt;/td&gt;
    &lt;td&gt;Finds a non-digit character&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;\s&lt;/td&gt;
    &lt;td&gt;Finds a white-space character&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;\S&lt;/td&gt;
    &lt;td&gt;Finds a character that is not white-space&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;\b&lt;/td&gt;
    &lt;td&gt;Finds a match only at the beginning or end of a word, beginning like this: \bHI, end like this: HI\b&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;\B&lt;/td&gt;
    &lt;td&gt;Finds a match, where \b doesn't&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;\n&lt;/td&gt;
    &lt;td&gt;Finds a line feed character&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;\f&lt;/td&gt;
    &lt;td&gt;Finds a form feed character&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;\r&lt;/td&gt;
    &lt;td&gt;Finds a carriage return character&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;\t&lt;/td&gt;
    &lt;td&gt;Finds a tab character&lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Quantifiers&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;th&gt;Quantifiers&lt;/th&gt;
&lt;th&gt;Description (n here is anything you want to match)&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;n{2}&lt;/td&gt;
&lt;td&gt;match only 2 instances of n&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;n{1,5}&lt;/td&gt;
&lt;td&gt;match at least 1 at most 5 instances of n&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;n{1,}&lt;/td&gt;
&lt;td&gt;match at least 1 instance of n&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;n+&lt;/td&gt;
&lt;td&gt;Shorthand to match 1 or more instances of n&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;n*&lt;/td&gt;
&lt;td&gt;Shorthand to match 0 or more instances of n&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;n?&lt;/td&gt;
&lt;td&gt;Shorthand to match 0 or 1 instances of n&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Miscellaneous&lt;a&gt;&lt;/a&gt;
&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%2Fimgs.xkcd.com%2Fcomics%2Fbackslashes.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%2Fimgs.xkcd.com%2Fcomics%2Fbackslashes.png" alt="escape sequence" width="571" height="207"&gt;&lt;/a&gt;&lt;/p&gt;

Meme on escape-sequence by &lt;a href="https://xkcd.com" rel="noopener noreferrer"&gt;xkcd&lt;/a&gt;




&lt;p&gt;'|' operator can be used to separate sub groups.&lt;br&gt;
'\1' operator(aka back-reference operator) is used to refer to previous subgroup of that index 1 in this case.&lt;br&gt;
There is no concatenation operator as such. Things written together are already concatenated.&lt;br&gt;
Some symbols that are used in expressions can't be used directly. '\' (backslash) is used to escape-sequence.&lt;br&gt;
Multiple bracket sets can be used like [a-z] and [0-9] can be combined in following way [a-z0-9] without '|' and space.&lt;br&gt;
^ and $ are used at beginning and end respectively however when ^ is used as [^\w]+ it is used to invert the selection. In this case no word will be selected i.e. only symbols and white spaces will be selected.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://jsfiddle.net/utkarsh48/uLwbz4km//embedded/js,result//dark" width="100%" height="600"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's see some interesting examples
&lt;/h2&gt;

&lt;p&gt;To validate an email, username and password&lt;br&gt;
&lt;iframe src="https://jsfiddle.net/utkarsh48/nvgeamhL//embedded/js,result//dark" width="100%" height="600"&gt;
&lt;/iframe&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%2Fz7xc7gxh5w6551kb82cm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz7xc7gxh5w6551kb82cm.jpg" alt="meme on regular expressions" width="625" height="342"&gt;&lt;/a&gt;&lt;/p&gt;
Values are screened by RegExp. for security purpose. By &lt;a href="https://quickmeme.com" rel="noopener noreferrer"&gt;Quickmeme&lt;/a&gt;



&lt;h2&gt;
  
  
  Real-world application of RegEx.&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Forms:&lt;/strong&gt; Usernames, Email addresses, passwords etc. are validated through RegEx. expressions. as seen above.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Search:&lt;/strong&gt; RegEx. are used to search for files and within files. Sometimes replacement is followed by search.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Replace:&lt;/strong&gt; With new updates in languages newer syntax come into play and sometimes older syntax are depreciated. Therefore changing each line of code would be a miserable. To ease the process there are programs that can convert syntax without damaging the functioning of original code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data Extraction:&lt;/strong&gt; RegEx. are used in SQL (a language that makes queries to database) to look for records matching some criteria.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2Fftw96ydwkc9ktbkso1tn.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%2Fftw96ydwkc9ktbkso1tn.png" alt="saved the day" width="600" height="607"&gt;&lt;/a&gt;&lt;/p&gt;
Saved the day. Source &lt;a href="https://xkcd.com" rel="noopener noreferrer"&gt;Xkcd&lt;/a&gt;



&lt;h3&gt;
  
  
  Summary&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;With Regular expression in your tool box, you can manipulate strings like pro!&lt;br&gt;
Otherwise your life would be much more difficult than it need to be. Learn more at &lt;a href="https://www.w3schools.com/jsref/jsref_obj_regexp.asp" rel="noopener noreferrer"&gt;W3school&lt;/a&gt;&lt;br&gt;
 &lt;a href="http://web.mit.edu/gnu/doc/html/regex_3.html" rel="noopener noreferrer"&gt;or here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>regex</category>
    </item>
  </channel>
</rss>
