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
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
Start the development server.
vercel dev -d
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
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')
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>
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>
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
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
}
Initialize go modules and add dependencies to the go.mod
file by running.
go mod init && go mod tidy
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>
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.
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
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.
That's it.
Here's the Github Repo.
pusti
Repository to accompany with the article at https://dev.to/liptanbiswas/creating-feedback-form-on-vercel-using-vue-and-golang-5fc1
Project setup
npm install
Compiles and hot-reloads for development
npm run serve
Compiles and minifies for production
npm run build
Lints and fixes files
npm run lint
Customize configuration
Here's the live form. Do let me know your feedback.
References: Vercel blog
Top comments (0)