<?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: Milan Maharjan</title>
    <description>The latest articles on DEV Community by Milan Maharjan (@milanmaharjan).</description>
    <link>https://dev.to/milanmaharjan</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%2F364595%2F562d6fdf-4775-4473-a171-5f1759e1cdf4.jpg</url>
      <title>DEV Community: Milan Maharjan</title>
      <link>https://dev.to/milanmaharjan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/milanmaharjan"/>
    <language>en</language>
    <item>
      <title>Build a custom Contact Form for your static website</title>
      <dc:creator>Milan Maharjan</dc:creator>
      <pubDate>Sun, 12 Apr 2020 15:30:00 +0000</pubDate>
      <link>https://dev.to/milanmaharjan/build-a-custom-contact-form-for-your-static-website-1665</link>
      <guid>https://dev.to/milanmaharjan/build-a-custom-contact-form-for-your-static-website-1665</guid>
      <description>&lt;p&gt;If your website doesn’t change that often and all the features you need can be implemented with a static site, then there is no point building a bulky dynamic site. After all static sites are fast, simple, costs low, easier to scale and more secure.&lt;/p&gt;

&lt;p&gt;Being said that, sometimes we need some features that a static sites can’t offer. Getting data from a contact form is one of them. But there’s a very easy way to do that.&lt;/p&gt;

&lt;p&gt;In this tutorial we will learn how to use google sheet as a backend to store the data submitted from a contact form and also send that information in email.&lt;/p&gt;

&lt;p&gt;We’ll be using&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://pages.github.com" rel="noopener noreferrer"&gt;GitHub Pages&lt;/a&gt; to host my static contact form (&lt;em&gt;free&lt;/em&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Contact form template by &lt;a href="https://colorlib.com/download/160/" rel="noopener noreferrer"&gt;Colorlib&lt;/a&gt; (&lt;em&gt;also free&lt;/em&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developers.google.com/apps-script/guides/sheets" rel="noopener noreferrer"&gt;Google App Script&lt;/a&gt; to use &lt;a href="https://docs.google.com/spreadsheets" rel="noopener noreferrer"&gt;Google Sheet&lt;/a&gt; as data storage and send notification in email (&lt;em&gt;also free&lt;/em&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’ll first create a url to submit the contact form to. Let’s begin !&lt;/p&gt;

&lt;p&gt;1) Open &lt;a href="https://docs.google.com/spreadsheets" rel="noopener noreferrer"&gt;Google Sheet&lt;/a&gt; and create a new sheet.&lt;/p&gt;

&lt;p&gt;2) Add the names of the input fields in your html form in the first row of the sheet. We’ll add &lt;code&gt;sn, name, email, subject&lt;/code&gt; and &lt;code&gt;message&lt;/code&gt; Field &lt;code&gt;sn&lt;/code&gt; is auto generated serial number and this is not included in the html form.&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%2Fcdn-images-1.medium.com%2Fmax%2F2588%2F1%2A891xJWYtiC2d6-16w7_NHg.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%2Fcdn-images-1.medium.com%2Fmax%2F2588%2F1%2A891xJWYtiC2d6-16w7_NHg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3) Click &lt;code&gt;Tools&lt;/code&gt; in menu bar, then click &lt;code&gt;Script Editor&lt;/code&gt;&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%2Fcdn-images-1.medium.com%2Fmax%2F2528%2F1%2AcJtymE7LU3TaJzVVUb3wqQ.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%2Fcdn-images-1.medium.com%2Fmax%2F2528%2F1%2AcJtymE7LU3TaJzVVUb3wqQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4) This will open a script editor page. Copy the following code and paste it in the script editor. This script will listen for a &lt;code&gt;POST&lt;/code&gt; request and add the submitted data as a new row in the google sheet and also send notification email. Don't forget to replace the email address in the script with yours. It's in the last line of the script.&lt;/p&gt;


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


&lt;p&gt;5) Save the script. Then click &lt;code&gt;Run &amp;gt; Run function &amp;gt; setup&lt;/code&gt; It will then ask for permission to access your google sheet and gmail. Just allow it. Then click &lt;code&gt;Publish &amp;gt; Deploy as web app&lt;/code&gt; Set project version as &lt;code&gt;new&lt;/code&gt;, execute the app as &lt;code&gt;me&lt;/code&gt; and who has the access to app as &lt;code&gt;Anyone, even anonymous&lt;/code&gt;. Then click deploy and it will display a web app url. Copy this url, we’ll need this later.&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AI5IGS_gfa-zCB9WO4_o0hA.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AI5IGS_gfa-zCB9WO4_o0hA.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That is all we need to do in google sheet. Now let’s setup our frontend.&lt;/p&gt;

&lt;p&gt;6) In your html form, let’s add few jQuery script to submit a POST request to the url we generated in step 5 above. Add following codes between script tag in your html. Replace the url in below code with your google script url and also replace the form class name.&lt;/p&gt;


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


&lt;p&gt;Whenever you submit the contact form, this jQuery function will do ajax request to the google script url with the form data as payload.&lt;/p&gt;

&lt;p&gt;Remember that the input field names of the form should be defined in the google sheet’s first row. You can add any number of input field in the form. Just define the field names in the google sheet and the submitted values will be populated in the sheet automatically.&lt;/p&gt;

&lt;p&gt;I have hosted my contact form using Github Pages. Check it out here &lt;a href="https://maharjanmilan.github.io/contact-form" rel="noopener noreferrer"&gt;https://maharjanmilan.github.io/contact-form&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once you submit the form, if the data submission was successful you’ll see a success popup. You can also replace this popup with other beautiful alternatives.&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%2Fcdn-images-1.medium.com%2Fmax%2F5024%2F1%2AD1aG9FOdm0bK-UdVUIEzAw.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%2Fcdn-images-1.medium.com%2Fmax%2F5024%2F1%2AD1aG9FOdm0bK-UdVUIEzAw.png" alt="[https://maharjanmilan.github.io/contact-form](https://maharjanmilan.github.io/contact-form/?)"&gt;&lt;/a&gt;&lt;em&gt;&lt;a href="https://maharjanmilan.github.io/contact-form/?" rel="noopener noreferrer"&gt;https://maharjanmilan.github.io/contact-form&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;7) Now you can see the contact details submitted from the form in your google sheet. You'll also receive an email with all the data.&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%2Fcdn-images-1.medium.com%2Fmax%2F3320%2F1%2AzRAIkWAkw2Hl6ro74_hSgA.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%2Fcdn-images-1.medium.com%2Fmax%2F3320%2F1%2AzRAIkWAkw2Hl6ro74_hSgA.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you need a date column to record the submitted date just add &lt;code&gt;Timestamp&lt;/code&gt; header right beside &lt;code&gt;message&lt;/code&gt; This field will auto-populate the submitted date.&lt;/p&gt;

&lt;p&gt;That’s it. As simple as that.&lt;/p&gt;

&lt;p&gt;Modify it slightly and you can create a newsletter form or even build a product order form. The possibilities are limitless.&lt;/p&gt;

&lt;p&gt;You can also clone my project &lt;a href="https://github.com/maharjanmilan/contact-form/" rel="noopener noreferrer"&gt;https://github.com/maharjanmilan/contact-form/&lt;/a&gt; and see the implementation there.&lt;/p&gt;

&lt;p&gt;If you want to learn how to deploy your static site to Github Pages see &lt;a href="https://pages.github.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. It is very easy. You can even use your custom domain name for free.&lt;/p&gt;

&lt;p&gt;There are lot of other free static hosting services like &lt;a href="https://www.netlify.com/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt;, &lt;a href="https://firebase.google.com/" rel="noopener noreferrer"&gt;Firebase&lt;/a&gt;, &lt;a href="https://aws.amazon.com/s3/" rel="noopener noreferrer"&gt;Amazon S3&lt;/a&gt;, &lt;a href="https://zeit.co/" rel="noopener noreferrer"&gt;Zeit&lt;/a&gt;, &lt;a href="https://getforge.com/" rel="noopener noreferrer"&gt;Forge&lt;/a&gt;. Check them out as well.&lt;/p&gt;

&lt;p&gt;&lt;del&gt;Btw you can also trigger the google sheet to send email with the form data. But that’s for another tutorial :)&lt;/del&gt; Since it was not a big change, I have included the email sending in the App script above. &lt;/p&gt;

&lt;p&gt;I hope this was helpful.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>html</category>
      <category>css</category>
      <category>googlesheets</category>
    </item>
    <item>
      <title>Continuous Deployment (CD) from Bitbucket to Cpanel/FTP Server</title>
      <dc:creator>Milan Maharjan</dc:creator>
      <pubDate>Sat, 11 Apr 2020 07:09:33 +0000</pubDate>
      <link>https://dev.to/milanmaharjan/continuous-deployment-cd-from-bitbucket-to-cpanel-ftp-server-2jn9</link>
      <guid>https://dev.to/milanmaharjan/continuous-deployment-cd-from-bitbucket-to-cpanel-ftp-server-2jn9</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--joc-6cr---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/1%2A5JlKsnKXhqWMfmVKSppFzg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--joc-6cr---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/1%2A5JlKsnKXhqWMfmVKSppFzg.jpeg" alt="bitbucket pipelines to ftp server"&gt;&lt;/a&gt;&lt;br&gt;
There has been a drastic rise of using virtual cloud servers to host apps. And a lot of developers implement CI/CD. It makes the deployment in the cloud easy and fast.&lt;/p&gt;

&lt;p&gt;A lot of apps no longer use FTPs or traditional shared hosting anymore. But there are still many of us who host their apps in shared hosting, because the app is simple and the cost is low as well. Today we’ll learn how to automatically deploy our code to shared hosting via FTP whenever something is pushed to bitbucket.&lt;/p&gt;

&lt;p&gt;Bitbucket has an integrated CI/CD service called &lt;a href="https://bitbucket.org/product/features/pipelines"&gt;Bitbucket Pipelines&lt;/a&gt; that allows us to automatically build, test and deploy our code. We’ll setup a pipeline by creating &lt;code&gt;bitbucket-pipelines.yml&lt;/code&gt; file in the root directory of our repository. In this file, we’ll add steps to deploy our app to FTP server when code is pushed to the master branch.&lt;/p&gt;

&lt;p&gt;Let’s Begin.&lt;/p&gt;

&lt;p&gt;I will be using a simple weather app written in Vue CLI &lt;a href="https://github.com/oxyyyyy/vue-weather"&gt;https://github.com/oxyyyyy/vue-weather&lt;/a&gt;. I have forked this repo to update the weather api keys in &lt;a href="https://github.com/maharjanmilan/vue-weather"&gt;https://github.com/maharjanmilan/vue-weather&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To import this Github repo to your Bitbucket, go to &lt;a href="https://bitbucket.org/repo/import"&gt;https://bitbucket.org/repo/import&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Gu6sG8JL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2572/1%2AkSJtVHWDanHc8BDFswIGAA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Gu6sG8JL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2572/1%2AkSJtVHWDanHc8BDFswIGAA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;bitbucket-pipelines.yml&lt;/code&gt; file in the root of the project.&lt;/p&gt;


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


&lt;p&gt;This is a build configuration for Docker. You can use any docker image from &lt;a href="https://hub.docker.com/"&gt;Docker Hub&lt;/a&gt; as your build environment. Here I have used &lt;code&gt;node:latest&lt;/code&gt; image. Under &lt;code&gt;branches&lt;/code&gt; I have specified &lt;code&gt;master&lt;/code&gt;. So this build will happen only when we push to master branch. Under &lt;code&gt;script&lt;/code&gt; I have mentioned few commands to run inside the container. Then I have used a ftp pipe provided by Bitbucket to deploy the code to ftp server. Under &lt;code&gt;variables&lt;/code&gt; we define our FTP parameters of Cpanel or any hosting service.&lt;/p&gt;

&lt;p&gt;You can see here that I have used pipeline environment variables. This can be defined under repository &lt;code&gt;Setting &amp;gt; Pipelines &amp;gt; Repository variables&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--76hcOB0F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/5378/1%2AWfHAMeAjr1LAeaWynkG6aw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--76hcOB0F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/5378/1%2AWfHAMeAjr1LAeaWynkG6aw.png" alt="Pipeline Environment Variables"&gt;&lt;/a&gt;&lt;em&gt;Pipeline Environment Variables&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You should always use pipeline environment variables for the sensitive informations.&lt;/p&gt;

&lt;p&gt;Once you have created and commited the file, click on &lt;code&gt;Pipelines&lt;/code&gt; menu and click &lt;code&gt;Enable&lt;/code&gt; button. Now the pipeline is enabled for this repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GccjWBUo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/5352/1%2ALx0fApoCXNBrTwmJV1yacQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GccjWBUo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/5352/1%2ALx0fApoCXNBrTwmJV1yacQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now whenever you push to master branch, the build process is triggered automatically. Here is what happens:&lt;/p&gt;

&lt;p&gt;Bitbucket will create a container with the code of current repository from the image we mentioned in the &lt;code&gt;yml&lt;/code&gt; file. In this case from &lt;code&gt;node:latest&lt;/code&gt; image.&lt;/p&gt;

&lt;p&gt;It then runs &lt;code&gt;yarn install&lt;/code&gt; to install all the dependencies js libraries.&lt;/p&gt;

&lt;p&gt;Since we are deploying the project in production, we don’t need all the codes from the repository. The &lt;code&gt;yarn run build&lt;/code&gt; command will compile the necessary code and store in &lt;code&gt;dist&lt;/code&gt; folder. We only need to deploy this folder.&lt;/p&gt;

&lt;p&gt;Bitbucket ftp pipe will then copy the &lt;code&gt;dist&lt;/code&gt; folder as defined in &lt;code&gt;$ftp_local_path&lt;/code&gt; variable to &lt;code&gt;$ftp_remote_path&lt;/code&gt; path in our FTP server.&lt;/p&gt;

&lt;p&gt;If you go to &lt;code&gt;Pipelines&lt;/code&gt; menu you can see the current pipeline being run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1vaWZMjE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3394/1%2A5vA1pdqLhXJm_f6JgAMm8A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1vaWZMjE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3394/1%2A5vA1pdqLhXJm_f6JgAMm8A.png" alt="List of pipelines"&gt;&lt;/a&gt;&lt;em&gt;List of pipelines&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can also click on specific pipeline and view the build steps and build logs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KPMtU_f6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4512/1%2AwPmnZyvD6j6nV2qtGgFYWg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KPMtU_f6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4512/1%2AwPmnZyvD6j6nV2qtGgFYWg.png" alt="Pipeline detail page"&gt;&lt;/a&gt;&lt;em&gt;Pipeline detail page&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It took 3m 28s for the whole build process. At the time of this writing Bitbucket provides free 50 build minutes, which shall be enough if you don’t push much. Also if you have to revert your changes, you can just click on old pipes and rerun it.&lt;/p&gt;

&lt;p&gt;The code should now be deployed to your FTP server. Mine was uploaded here: &lt;a href="http://weather.milanmaharjan.com.np/"&gt;http://weather.milanmaharjan.com.np/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LJ2wyWGS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4044/1%2ArRRs8CeZ_xKh7tHVRK-7-A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LJ2wyWGS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4044/1%2ArRRs8CeZ_xKh7tHVRK-7-A.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is as simple as that.&lt;/p&gt;

&lt;p&gt;If your app is not working update the api key for Weatherbit in &lt;code&gt;src/constants.js&lt;/code&gt; file. You can create api key for free from &lt;a href="https://www.weatherbit.io/"&gt;Weatherbit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://about.gitlab.com/"&gt;Gitlab&lt;/a&gt; also has a similar integrated CI/CD service and they provide 2000 build minutes per month for free. I am also planning to write a tutorial on Gitlab as well.&lt;/p&gt;

&lt;p&gt;I hope this tutorial was helpful for you. If you have any issues, let me know in the comments below.&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>bitbucketpipelines</category>
      <category>autodeloyment</category>
      <category>cpanel</category>
    </item>
  </channel>
</rss>
