Adding Netlify Forms On Your Nuxt Website

Kim Björkman
3 min readJul 9, 2019

--

I’ve recently been spending some time learning the ins and outs of Nuxt, and once you get the hang of it, it makes development with Vue a very pleasant and enriching experience. Nuxt abstracts away the client/server distribution and sets up a very fast workflow for you, no more worrying about routing etc.

As with learning any new framework you will run into obstacles, I ran into one when trying to set up a contact section using Netlify Forms.

PS. Before continuing on here make sure you have set up HTTPS on your site, we don’t want to send data over an unencrypted connection.

Creating the form

The first thing you have to do when setting up Forms is to create the html in your view:

<form 
name="contactus"
action="/thanks"
method="post"
netlify
netlify-honeypot="bot-field"
>
// Hidden input to check for bots
<input type="hidden" name="form-name" value="contactus" />
<div>
<label for="name">Name:</label>
<input type="text" name="name" required/>
</div>
<div>
<input type="email" name="email" required/>
<label for="email">Email:</label>
</div>
<div>
<textarea name="message" required></textarea>
<label for="message">Message:</label>
</div>
<button type="submit" value="Send message">Send</button>
</form>

There are some points here that are noteworthy:

  • The action attribute. When the form is submitted Netlify will redirect you to the route you specify here. In our example we have created a page called thanks in our pages folder.
  • The netlify attribute is used to tell Netlify to handle the form.
  • data-netlify-honeypot=”bot-field” is used in combination with a hidden field with a name that corresponds to the value of of the attribute to check for bots. It’s hidden so only a bot would fill it in.
  • A hidden input field with name=”form-name” and with the value set to the name of your form, in this case value=”contactus” since that’s the name we give the form on line 2. This is used by Netlify to check for bots.
  • Make sure the inputs all have valid names so that we can later connect this to the backend properly.

Done!… Or are we?

Most other texts I found when researching this ends here. But we are using Nuxt and therefore also Vue.

By default Vue renders client side but the Netlify post processing bots expect HTML on site deploy. Any netlify form attribute tags included in a Vue app would only be inserted into the DOM client-side, rather than in the HTML and thereby runs the risk of being totally overlooked by the build bots.

This is exactly what happens in our Nuxt page. No form will get submitted because Netlifys build bots are overlooking the form. To prevent this we need to add a skeleton of our form on the page somehow. Nuxt uses an app.template.html file inside /nuxt/views to render its page template, where it inserts its virtual DOM. But if you add your skeleton here, you will notice that whenever you recompile your application the skeleton you just added will get removed, so this is a no-no.

What we are going to do is tell Nuxt to use our own template, we do this by creating a file called app.html at the root of our application. Inside this file you want to copy the template from the /nuxt/views folder and paste it into this new folder. And add your own form skeleton at the top of the page. Your app.html file might then look something like this:

<!DOCTYPE html><html {{ HTML_ATTRS }}>  <head {{ HEAD_ATTRS }}>    {{ HEAD }}  </head>  <body {{ BODY_ATTRS }}>  <form name="contactus" netlify netlify-honeypot="bot-field" hidden>    <input type="text" name="name" />    <input type="radio" name="email" />    <textarea name="message"></textarea>  </form>  {{ APP }}</body></html>

Notice that the form and the inputs has the same name as our real form. It also has the netlify and netlify-honeypot attributes.

Now when we push our site to production we should have a working form!

Good work! 🎉

--

--

Kim Björkman

Developer based in Sweden/Japan. I write about problems and interesting things I run into. Currently happily coding at `Sunny at Sea` in Stockholm, Sweden.