DEV Community

Cover image for Creating Feedback Form on Vercel using Vue and Golang
Liptan Biswas
Liptan Biswas

Posted on • Updated on

Creating Feedback Form on Vercel using Vue and Golang

You might be wondering why someone wants to set up a feedback form from scratch. It's just a feedback form and it's so simple.

I am well aware that there are a lot of Saas applications I could have used to set up such a form, yet I took a far complex approach to achieve a simple task. But by doing this, along the way I learned a few things. Which is what matters in this case, since the sole purpose of going through the trouble is to get some amount of idea and hands-on on technologies like, using Vercel, Vue, etc. I already had a working knowledge of Golang. I had heard a lot about how Vercel makes deploying frontend application so simple, so wanted to give it a try.

Components

The frontend of the form is written in Vue.js, which, on submit sends a POST request to a serverless application written in Golang. Go application sends an email to me using Sendgrid. This Vue application and Golang app are both deployed on Vercel.

Creating the Frontend

Create a new Vue project.

npx @vue/cli create -d my-feedback-form && cd my-feedback-form
Enter fullscreen mode Exit fullscreen mode

If the command does not work, you probably don't have Nodejs installed, you will need to install it.

Although, we can use npm run serve to run our development server, let's install Vercel cli as well. Vercel cli will help us to test our Golang serverless application as well.

npm i -g vercel
Enter fullscreen mode Exit fullscreen mode

Start the development server.

vercel dev -d
Enter fullscreen mode Exit fullscreen mode

It will ask you a series of questions. Go with the default options. You may need to provide your email address. Open your web browser and go to http://localhost:3000, you should the Vue welcome page.

I have used bootstrap as well to make the form look a little better. Install bootstrap by running.

npm i bootstrap-vue bootstrap
Enter fullscreen mode Exit fullscreen mode

Update the src/main.js file with the following content.

import Vue from 'vue'
import App from './App.vue'
import BootstrapVue from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'

Vue.use(BootstrapVue)
Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')
Enter fullscreen mode Exit fullscreen mode

Now, Create a file at src/components/Form.vue with the following content.

<template>
  <div class="row justify-content-center">
    <div>
      <h2 v-if="!status">Please provide your feedback!</h2>

      <b-form v-if="!status" @submit="sendForm">
        <b-form-group>
          <b-form-input type="text" name="name" v-model="name" placeholder="Enter your name..."></b-form-input>
        </b-form-group>
        <b-form-group>
          <b-form-input type="email" name="email" v-model="email" placeholder="Enter your email..." required>
          </b-form-input>
        </b-form-group>
        <b-form-group>
          <b-form-textarea type="text" name="message" v-model="message" placeholder="Leave a feedback..." required>
          </b-form-textarea>
        </b-form-group>
        <b-form-group>
          <b-button block variant="primary" type="submit">Send</b-button>
        </b-form-group>
      </b-form>

      <h2 v-if="status === 'success'">Thank you, your feedback is submitted!</h2>
      <h2 v-if="status === 'error'">Oops, something went wrong. Please try again.</h2>
    </div>
  </div>
</template>

<script>
  export default {
    name: 'Form',
    data: function () {
      return {
        status: null,
        name: null,
        email: null,
        message: null
      }
    },
    methods: {
      sendForm: function (event) {
        event.preventDefault()
        fetch('/api/sendmail', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            Accept: 'application/json'
          },
          body: JSON.stringify({ name: this.name, email: this.email, message: this.message })
        })
          .then((response) => {
            if (response.status < 299) {
              this.status = 'success'
            }
            else {
              this.status = 'error'
            }
          })
      }
    }
  }
</script>
Enter fullscreen mode Exit fullscreen mode

Update the src/App.vue file with the following content.

<template>
  <div id="app">
    <Form />
  </div>
</template>

<script>
  import Form from './components/Form.vue'

  export default {
    name: 'App',
    components: {
      Form
    }
  }
</script>
Enter fullscreen mode Exit fullscreen mode

We don't need src/components/HelloWorld.vue, it can be removed.

Check your browser, you should see the feedback form. On filling the form and clicking Submit, you should receive an error saying Oops, something went wrong. Please try again. It's because on clicking submit, the Vue application is sending a POST request on the /api/sendmail endpoint. We do not have it implemented.

Let's implement it using Golang. Vercel provides a powerful feature of adding our backend code in the same repository. It supports some of the popular languages and is deployed along with your front-end application as a serverless function.

Creating the backend

There is no additional configuration needed to deploy a serverless api using Vercel. Code written in api directory will be read and deployed as a function on the same domain as your frontend, at path /api. Read more here.

Create a directory named api and switch to it using

mkdir api && cd api
Enter fullscreen mode Exit fullscreen mode

Create a new file sendmail.go.

Put the following code in the file.

package handler

import (
    "encoding/json"
    "net/http"
    "os"

    "github.com/sendgrid/sendgrid-go"
    "github.com/sendgrid/sendgrid-go/helpers/mail"
)

//Feedback is feedback struct
type Feedback struct {
    Name    string
    Email   string
    Message string
}

//Handler is the default handler
func Handler(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path != "/api/sendmail" || r.Method != "POST" {
        http.Error(w, "404 not found.", http.StatusNotFound)
        return
    }

    var fb Feedback
    err := json.NewDecoder(r.Body).Decode(&fb)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    res, body, err := SendMail(fb)
    if err != nil {
        println("Error sending Email: %v", err)
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    w.WriteHeader(res)
    w.Header().Set("content-type", "application/json")
    w.Write([]byte(body))
    return
}

//SendMail sends the email using Sendgrid
func SendMail(f Feedback) (res int, out string, err error) {
    from := mail.NewEmail(f.Name, f.Email)
    subject := "[Feedback] on something"
    to := mail.NewEmail("Liptan Biswas", "<your-email-address>")
    message := mail.NewSingleEmail(from, subject, to, "", f.Message)
    client := sendgrid.NewSendClient(os.Getenv("SENDGRID_API_KEY"))
    r, err := client.Send(message)
    if err != nil {
        return r.StatusCode, r.Body, err
    }
    return r.StatusCode, r.Body, nil
}
Enter fullscreen mode Exit fullscreen mode

Initialize go modules and add dependencies to the go.mod file by running.

go mod init && go mod tidy
Enter fullscreen mode Exit fullscreen mode

During serverless function deployment to Vercel, these dependencies are automatically discovered and installed.

Follow Sendgrid documentation and obtain an API key from Sendgrid.

Come back to the project root and create a .env file and put your Sendgrid API key in that.

SENDGRID_API_KEY=<YOUR-API-KEY>
Enter fullscreen mode Exit fullscreen mode

Make sure to append .env into .gitignore otherwise you may mistakenly commit it.

If you have Postman, fire it up and send a POST request to http://localhost:3000/api/sendmail. You may skip if you are confident that the API works.

Postman Response

You should see a 202 response if Sendgrid accepted your email.

Now, we can head back to the browser and submit the form to test it once, you should get both the emails in your inbox.

Deploy to Vercel

Deploying your application to Vercel is the easiest step. Just run the command.

vercel --prod
Enter fullscreen mode Exit fullscreen mode

and it will be deployed. You may want to push the code to git and connect the repo to Vercel. But, this works as well. While Vercel is deploying your application, go to the Vercel dashboard, and find your application. Navigate to Your App >> Settings >> Environment Variables. Add the SENDGRID_API_KEY environment variable.

You will need to redeploy for the env variable to take effect. Just, run the vercel --prod command again.

If you connect your repository to Vercel, you won't need to run this command every time you want to deploy. Just push the commit and Vercel will automatically pick up the change and deploy it. It will also comment the deployed URL on the commit.

Vercel comment

That's it.

Here's the Github Repo.

Here's the live form. Do let me know your feedback.

References: Vercel blog

Oldest comments (0)