Contact Form in Gatsby JS and Firebase realtime database

January 22, 2020

Our website has a contact form where a visitor can leave a message to us.

Contact form with firebase

Given that DevToolsDaily is a static website implemented in React/GatsbyJS and hosted in Netlify, we didn't want to add a tranditional web server into the picture (yet).


Options we considered

We started researching the options we have for contact form.

Good starting point is Gatsby's guide: Building a Contact Form

  1. Netlify form submissions

You can see documentation here Netlify form handling feature;

For JS generated forms like GatsbyJS the setup is slightly different.

  1. Third party form submissions

Third party form submissions like getform or formspree seem to be trivial to setup and use.

  1. Lambda + any cloud DB.

Very popular choice for any API + storage layer are Netlify Functions + cloud storages like FaunaDB or "MongoDB Atlas".

  1. Firebase

    • Firebase allows direct web client to cloud DB connection, no need to have web-server layer in between.
    • Free limits seem pretty generous.
    • we know we need to add Auth at some point, so doing contact form would be a good testing ground.
    • I was considering firebase before but it appeared to be too much work, in reality it took only 20 minutes.

How we setup contact form with Firebase

1. Signup for Firebase

Signup for Firebase and setup realtime database (you might want to try "Firestore", we went with realtime database due to it's very simple storage model which works for now).

FireBase database

2. setup security rules

This is very important given that you open your DB connection to public internet via website. You should probably read full guide here.

For contact form, we don't want anybody to read any data, and we want anybody be able to write for a specific key.

My rules look like this:

  "rules": {
    "contacts": {
       "$contactId": {
       	".read": false,
        ".write": true,
        ".validate": "newData.hasChildren(['email', 'message'])",
        "email": {
          ".validate": "newData.isString() && newData.val().length > 0"
        },
        "message": {
		  ".validate": "newData.isString() && newData.val().length > 0"
        }
       }
    }
  }

explanation:

  • permissions: nobody can read anything, you can write into specific id
  • validatons: email and message should not be empty

3. install gatsby plugin + configure keys

follow instructions here https://www.gatsbyjs.com/plugins/gatsby-plugin-firebase/

4. creating contact form + handler

how to submit data to firebase:

const contactsRef = firebase
    .database()
    .ref("/contacts");

const newContactRef = contactsRef.push();
newContactRef.set({
    email: email,
    message: message,
    createdAt: Date.now(),
}, (error) => {
    if (error) {
        console.log("failed to write data");
    } else {
        setSuccess(true);
    }
});

(See more documentation here - https://firebase.google.com/docs/database/web/lists-of-data)

part of JSX form for reference.

    <div className=" contact-get-backtext-xs italic text-gray-700 mb-3">We will reply as soon as possible.</div>
        <div className="flex flex-wrap -mx-3 mb-6">
            <div className="w-full px-3">
            <label className="block tracking-wide mb-2" htmlFor="email">
                Your e-mail
            </label>
            <input id="email" name="email" type="email" className="w-full" value={email} onChange={(e) => setEmail(e.target.value)}/>
            </div>
        </div>
        <div className="flex flex-wrap -mx-3 mb-6">
            <div className="w-full px-3">
            <label className="block tracking-wide mb-2" htmlFor="message">
                Your message
            </label>
            <textarea name="message" id="message" value={message} className="w-full h-48" onChange={(e) => setMessage(e.target.value)}></textarea>
            </div>
        </div>
        <div className="md:flex items-end">
            <div className="w-full text-right">
                <PrimaryButton type="button" onClick={onSubmit}>Submit</PrimaryButton>
            </div>
        </div>

5. see submissions in firebase UI

See data in Firebase database


This article was originally published in DevToolsDaily blog