<?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>Forem: Kevin</title>
    <description>The latest articles on Forem by Kevin (@kevinc).</description>
    <link>https://forem.com/kevinc</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%2F497246%2Fa17118d3-b205-493b-bb53-e57239aa0d65.jpeg</url>
      <title>Forem: Kevin</title>
      <link>https://forem.com/kevinc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kevinc"/>
    <language>en</language>
    <item>
      <title>Create and deploy your Telegram bot HERE entirely free!</title>
      <dc:creator>Kevin</dc:creator>
      <pubDate>Fri, 02 Sep 2022 07:52:39 +0000</pubDate>
      <link>https://forem.com/kevinc/create-and-deploy-your-telegram-bot-here-entirely-free-4cgc</link>
      <guid>https://forem.com/kevinc/create-and-deploy-your-telegram-bot-here-entirely-free-4cgc</guid>
      <description>&lt;p&gt;In this tutorial, I will be showing you how you can deploy your telegram bot and keep it running 24/7 entirely for free.&lt;/p&gt;

&lt;p&gt;For telegram bot development, there are generally 2 methods used: polling and webhooks. Many tutorials out there make use of polling using a NodeJS or Python server, that listens to any messages received by the bot. This means that in order to deploy it, we would need a server running 24/7 that keeps polling for updates. There aren’t many free options available to keep a server running (the most common one would be Heroku, but once the server sleeps, there isn’t a good way to get it up again to continue responding to messages)&lt;/p&gt;

&lt;p&gt;Today, we will explore the options of webhooks. Setting a webhook for your telegram bot means that whenever your bot receives a new message, telegram will send that update to your pre-defined webhook endpoint. From our custom endpoint, we are then free to do whatever we want with this knowledge that our bot has received a message, and we can respond to it.&lt;/p&gt;

&lt;p&gt;For example, when our bot receives a message from a user, telegram will send a POST request with a payload containing information about that message (the user, message text, time, etc) to our pre-defined endpoint. Our endpoint will receive that POST request with the payload, and with that, we can respond to the user.&lt;/p&gt;

&lt;p&gt;But does this mean we will also need a server to accept these POST requests? Yes, but we do not need the server to be running 24/7. Instead, we will use serverless functions. There are many free serverless function options available: Cloudflare Workers, Vercel Serverless functions, etc.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will utilise Cloudflare Workers to create a POST endpoint which we will set up as our webhook for our Telegram bot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Creating a new Cloudflare Worker&lt;/li&gt;
&lt;li&gt;Setting webhooks for our Telegram bot&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  1. Creating a new Cloudflare Worker
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to dash.cloudflare.com and login (or sign up)&lt;/li&gt;
&lt;li&gt;On the sidebar, click on ‘Workers’&lt;/li&gt;
&lt;li&gt;Click on ‘Create a service’ to create your new worker&lt;/li&gt;
&lt;li&gt;Enter a name for your new worker and select the ‘HTTP handler’ as the starter, and click on ‘Create service’&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fmgjuAZB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e3ylh05og7ckyu46f36a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fmgjuAZB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e3ylh05og7ckyu46f36a.png" alt="Creating worker" width="831" height="782"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Once your service has been created, click on ‘Quick Edit’ to edit your worker directly in the browser&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xtm54_J5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1jwdk31d20x52o3qamez.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xtm54_J5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1jwdk31d20x52o3qamez.png" alt="Quick edit" width="880" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now, in your editor, you should be seeing the default code for a new Cloudflare worker.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&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;fetch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&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;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello world&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The logic of how we are going to handle the incoming request will be done in the &lt;code&gt;handleRequest&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;At this point, it is good to know what is the payload that Telegram will be sending to us.&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"update_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1140&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&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;"message_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;73&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"from"&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"id of user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"is_bot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"first_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name of user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"username of user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"language_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"en"&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;"chat"&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;id&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;chat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"first_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name of user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"username of user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"private"&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;"date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1662102031&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hi"&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;From the payload, we are able to tell who the user is, what is the chat that the user is sending (important for group chats) and what is the message text. As a start, lets make our bot echo the user’s message, but add an ‘over’ at the end of the message.&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
    &lt;span class="c1"&gt;// Getting the POST request JSON payload&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
      &lt;span class="c1"&gt;// Checking if the payload comes from Telegram&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chatId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; over&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://api.telegram.org/bot&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/sendMessage?chat_id=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;chatId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;text=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;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="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; 
      &lt;span class="c1"&gt;// Calling the API endpoint to send a telegram message&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OK&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Doesn't really matter&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code snippet, we check if the incoming request is a POST, and whether the payload contains the important information from Telegram. We get the chatId and text from the payload, and we generate a unique URL which we will call GET to, which will send a message via our bot programatically. One thing is still missing, which is the &lt;code&gt;${API_KEY}&lt;/code&gt;. This is where the bot API token will be substituted into, and we can set this value via the Cloudflare Workers settings.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go back to the your worker’s dashboard by clicking on ‘Save &amp;amp; Deploy’ and then exiting out of the editor.&lt;/li&gt;
&lt;li&gt;Under the settings panel, click on variables. Here you can set the environment variable for the worker.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b2Bpyd3U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/etx2c5xa3ezyozy0j41b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b2Bpyd3U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/etx2c5xa3ezyozy0j41b.png" alt="Setting env variables" width="880" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on ‘Add variable’ and input the variable name as API_KEY and the value as the bot’s API token and save your settings.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  2. Setting webhooks for our bot
&lt;/h1&gt;

&lt;p&gt;Now, with our endpoint ready, all that is left to do is to set the webhook of our bot to our custom endpoint.&lt;/p&gt;

&lt;p&gt;With our bot API token, and the URL of our new worker (which should be ending with workers.dev), substitute the values into this URL and simply copy and paste it into your browser and enter&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;replace with bot api token&amp;gt;/setWebhook?url=&amp;lt;replace with our worker url&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see this as a response, you’re all set!&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="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"ok"&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="nl"&gt;"result"&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="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Webhook was set"&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;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fIb8sqQn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lumh6loi1ab6t1mk7zpe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fIb8sqQn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lumh6loi1ab6t1mk7zpe.png" alt="tele message" width="368" height="88"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wasn’t that easy?
&lt;/h2&gt;

&lt;p&gt;So now you have set up your telegram bot which is able to run 24/7 entirely for free! You can customise this code to make your bot do anything you want. In a future tutorial, I will be showing you how to use Cloudflare KV to setup a simple database for your bot, to retain user data and enhance the capabilites of your bot! It’s really simple too, so like this tutorial if you want to see more!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>free</category>
    </item>
    <item>
      <title>Improve Your Team's Productivity with Vercel's Preview Deployments</title>
      <dc:creator>Kevin</dc:creator>
      <pubDate>Sun, 27 Mar 2022 17:37:58 +0000</pubDate>
      <link>https://forem.com/kevinc/improve-your-teams-productivity-with-vercels-preview-deployments-3h41</link>
      <guid>https://forem.com/kevinc/improve-your-teams-productivity-with-vercels-preview-deployments-3h41</guid>
      <description>&lt;p&gt;It's no secret that I love using Vercel. Not only does it provide me with free hosting and serverless functions, it also helps me to improve my productivity through CI/CD as a web developer. In this article, I will show you how your team can improve productivity using Vercel's free preview deployments. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9nLgyEaf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lqe3fdd6rcva3grwr2mh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9nLgyEaf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lqe3fdd6rcva3grwr2mh.png" alt="Image description" width="880" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What are preview deployments? In short, they are deployments for your branches that aren't your 'main' branch, and they have a unique URL so that you or your code reviewers do not have to switch branches or clone to preview the changes. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ztHHI-e7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0t5n3dc38q60ps902t4n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ztHHI-e7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0t5n3dc38q60ps902t4n.png" alt="Image description" width="880" height="161"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;For example, you have a project hosted on Vercel with the domain myverycoolproject.vercel.app, and it is linked to your 'main' branch on GitHub. If you have another branch, and made a PR, Vercel automatically detects this, and deploys your changes to a separate URL, perhaps like myverycoolproject-f9n834234.vercel.app. With this preview URL, it allows you to immediately deploy the changes in that PR, without affecting your main deployment. Your team can preview the changes of the PR in a matter of seconds, and review the PR. Once the PR is approved and merged, the main deployment will then be updated with the changes.&lt;/p&gt;

&lt;p&gt;To me, this saves a lot of time as I do not have to manually change branches and run the project on my device (or sometimes even clone the project). It makes code reviews a breeze, which improves the reliability and code quality of your project. I feel that this is such an important feature which should be in every CI/CD pipeline for a web development project, so try it out now!&lt;/p&gt;

&lt;p&gt;To learn how to integrate Vercel into your projects, check out my other articles here: &lt;br&gt;
&lt;a href="https://dev.to/kevinc/continuous-deployment-for-nodejs-projects-using-vercel-3bhd"&gt;Continuous Deployment for NodeJS Projects using Vercel&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/kevinc/how-to-setup-continuous-integration-for-your-nodejs-project-gei"&gt;How to setup Continuous Integration for your NodeJS project&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>productivity</category>
      <category>free</category>
    </item>
    <item>
      <title>Continuous Deployment for NodeJS Projects using Vercel</title>
      <dc:creator>Kevin</dc:creator>
      <pubDate>Fri, 23 Oct 2020 17:49:50 +0000</pubDate>
      <link>https://forem.com/kevinc/continuous-deployment-for-nodejs-projects-using-vercel-3bhd</link>
      <guid>https://forem.com/kevinc/continuous-deployment-for-nodejs-projects-using-vercel-3bhd</guid>
      <description>&lt;h1&gt;
  
  
  What is Continuous Deployment?
&lt;/h1&gt;

&lt;p&gt;Continuous Deployment (CD) is a software release process, automating the deployment of code to production. It is an extension of Continuous Integration, where the new changes added into the main branch will be released into production. This process is ideal for teams who want to get their new features or bug fixes out to the public as quickly as possible.&lt;/p&gt;

&lt;p&gt;In order to minimise the risk to deploying problematic code, a robust and comprehensive set of automated tests need to be in place. This ensures that new code being merged into the main branch (and subsequently deployed) is deployment ready and bug-free. In doing so, software development teams can automate their workflow processes, and do away with the need of manual deployment. This makes it easy for teams to release their new builds to production, encouraging small and incremental builds, rather than all at once, thus reducing the risk of each deployment. &lt;/p&gt;

&lt;p&gt;However, if a team requires approval by higher authority, an alternative would be Continuous Delivery. Continuous Delivery is similar to Continuous Deployment, but without automatically deploying the changes to production. Although the deployment to production is done manually, the Continuous Delivery pipeline ensures that once the authorisation is given to release the build, the build is production ready and can be released at any time. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fp9lmtgo54beiiycr0sgt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fp9lmtgo54beiiycr0sgt.png" alt="download"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are many tools available to facilitate this workflow, like Jenkins, TeamCity and GitLab, but in this tutorial, I will be showing you a free alternative where you can have CD for your web applications and have them hosted in their domain for free. &lt;/p&gt;

&lt;h1&gt;
  
  
  Why Vercel?
&lt;/h1&gt;

&lt;p&gt;Vercel allows you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Host your frontend project in their domain (vercel.app)&lt;/li&gt;
&lt;li&gt;Integrate with GitHub to enable CD on your projects&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Free!!!&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Setting up CD in Vercel
&lt;/h1&gt;

&lt;p&gt;For this tutorial, I will be setting up hosting and CD for a blank Create-React-Application in my GitHub repository. &lt;/p&gt;

&lt;p&gt;Once you have linked your GitHub account with Vercel, you will be greeted with the dashboard page. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftpb1hrfk61b2blni9lm6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftpb1hrfk61b2blni9lm6.png" alt="Screenshot 2020-10-24 at 12.24.11 AM"&gt;&lt;/a&gt;&lt;br&gt;
Click on the 'Import Project' button on the right. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgt0ynl61rhzzpgd0xaq8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgt0ynl61rhzzpgd0xaq8.png" alt="Screenshot 2020-10-24 at 12.49.37 AM"&gt;&lt;/a&gt;&lt;br&gt;
Depending on what you want, you can either import from your Git repository, or use one of their boilerplate template to get your project started. In this tutorial we will be importing from Git. Click on the blue continue button and enter the URL to your Git repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5uj854ozy1kz36bva4nt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5uj854ozy1kz36bva4nt.png" alt="Screenshot 2020-10-24 at 1.13.04 AM"&gt;&lt;/a&gt;&lt;br&gt;
Once the project has been imported, you can name your vercel project. This name will be used to host your project &lt;code&gt;&amp;lt;PROJECT NAME&amp;gt;.vercel.app&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are many framework presets that Vercel provides. It usually automatically detects the type of project that you have imported and recommends the preset according. This preset will set the defaults for the build command and output directory in the 'Build and Output Settings' section, but you can override it depending on your project. &lt;/p&gt;

&lt;p&gt;You can also provide any environment variables that the project requires like API keys in the 'Environment Variables' section. &lt;/p&gt;

&lt;p&gt;Lastly, if the Git repository that you imported does not have the frontend files in the root directory, you can set the correct directory on the 'Select root directory' at the top of the dialog. &lt;/p&gt;

&lt;p&gt;Once you are satisfied with the settings, click on deploy and sit back and relax!&lt;/p&gt;

&lt;p&gt;When Vercel has successfully deployed your application, your Git repo is now also configured for Continuous Deployment. Whenever a new PR is made, Vercel will automatically build the application and provide a live build of that version of the application. From these builds, you can test out the features of the new PR, while maintaining the production build in the main link. If you are satisfied, you can merge the PR and Vercel will update the production version of your application with the new changes, and viola! Your new changes have been deployed to production in a click of a button. &lt;/p&gt;

&lt;p&gt;There are many CI/CD tools available but Vercel is my favourite. It is so easy to setup, the layout of their website is clean and simple to use, and once you set up your project in Vercel, it does everything by itself and you don't have to worry about deployments anymore!&lt;/p&gt;

</description>
      <category>node</category>
      <category>vercel</category>
      <category>cd</category>
      <category>devops</category>
    </item>
    <item>
      <title>How to setup Continuous Integration for your NodeJS project</title>
      <dc:creator>Kevin</dc:creator>
      <pubDate>Fri, 23 Oct 2020 17:34:44 +0000</pubDate>
      <link>https://forem.com/kevinc/how-to-setup-continuous-integration-for-your-nodejs-project-gei</link>
      <guid>https://forem.com/kevinc/how-to-setup-continuous-integration-for-your-nodejs-project-gei</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1d3yxt3x6kwzbxnejda2.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1d3yxt3x6kwzbxnejda2.jpeg" alt="Photo by Yancy Min on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Continuous Integration (CI) is a software development practice of merging your code with the main branch frequently. This aims to help developers catch bugs early, and also to prevent a developer's worst nightmare, known as 'merge hell'. Merge hell happens when you are about to merge with the main branch, but you are met with a long list of merge conflicts. Imagine after working for on a feature for months and you're finally done, but now you have to untangle this mess of merge conflicts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fte7wi6fghmriyq24wn0n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fte7wi6fghmriyq24wn0n.png" alt="1_LjDom9HWO5bSvL0Ub_xvpg"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;CI aims to help solve this issue by having developers merge their code with the main branch once or multiple times a day. The principle is: if it hurts, do it often, then it will not hurt so much. By merging code multiple times a day, this means that even if there is a merge conflict, it would be a relatively small one, since the changes is only up till the previous day at most. This makes the merge conflict easy to resolve, and developers can easily get on with their day. It also allows developers to catch issues and solve them early.&lt;/p&gt;

&lt;p&gt;With developers merging more frequently, sometimes the code being merged could be half written code, or code that have not been tested extensively. That is why another important aspect of CI is the use of automated testing. Automated testing ensures that the code being merged does not contain any bugs or breaking changes that would affect the work of other developers. This ensures that problems are resolved before they are merged into the main branch.&lt;/p&gt;

&lt;p&gt;In this tutorial, I will be sharing how you can setup CI for your project by implementing automated testing into your NodeJS project. For more information about writing test cases for NodeJS, I recommend reading the following articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to Unit Test with NodeJS?: &lt;a href="https://medium.com/serverlessguru/how-to-unit-test-with-nodejs-76967019ba56" rel="noopener noreferrer"&gt;https://medium.com/serverlessguru/how-to-unit-test-with-nodejs-76967019ba56&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Testing in Node.js Using Mocha and Chai: &lt;a href="https://medium.com/better-programming/testing-in-node-js-using-mocha-and-chai-part-1-d5a9e91f4b06" rel="noopener noreferrer"&gt;https://medium.com/better-programming/testing-in-node-js-using-mocha-and-chai-part-1-d5a9e91f4b06&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Implementing automated testing in GitHub for your NodeJS project
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Pre-requisites:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Your project should be on GitHub&lt;/li&gt;
&lt;li&gt;Your project should be able to run tests locally using the 'npm test' command&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Go to &lt;a href="https://travis-ci.org/" rel="noopener noreferrer"&gt;Travis CI&lt;/a&gt; and login with your GitHub account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F730jazajmke8013g86mf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F730jazajmke8013g86mf.png" alt="Screenshot 2020-10-22 at 2.53.25 PM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the '+' on the left sidebar, next to the 'My Repositories' tab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7b15cwhsg23ry9cbfsfj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7b15cwhsg23ry9cbfsfj.png" alt="1_YJVmrMKrFx1DMn8UafuLiA"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Search for the repository you want to use, and click on the toggle button on the right.&lt;/p&gt;

&lt;p&gt;Travis is now enabled for your project! Whenever a new push is made, Travis will try to build it. However, Travis doesn't know what exactly to do yet, and we need to tell it what to do by using the '.travis.yml' file.&lt;/p&gt;

&lt;p&gt;In the root directory of your project, create a new .travis.yml file and enter this into the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;language: node_js
node_js:
 - "stable"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now simply add this .travis.yml file into your github repository, and make a new PR and viola! You should see a yellow dot next to your PR, indicating that a Travis build is running, and a green dot if it passes all test cases, or a red cross if it fails your test cases.&lt;/p&gt;

</description>
      <category>node</category>
      <category>ci</category>
      <category>devops</category>
      <category>travisci</category>
    </item>
  </channel>
</rss>
