Build a Jamstack subscription form with Netlify forms and Fauna - Part 2
Tags: jamstack, javascript, fauna, netlify
Published: 2021-05-14 09:56:25

Hey there 👋! Welcome to part-2 of the tutorial. I hope you enjoyed part-1 in building a Jamstack form using `Netlify Forms`. This article will learn about storing the form data into the `Fauna` data store.

> Here is the link to part-1 of the tutorial: [Build a Jamstack subscription form with Netlify forms and Fauna - Part 1](https://blog.greenroots.info/build-a-jamstack-subscription-form-with-netlify-forms-and-fauna-part-1-ckoky1dah03iz2gs1f6tz3suq)

# Recap
So far, we have
- Created a Subscription page using `HTML` and `CSS`. The highlight of the page was a form with a few input fields and a button.
- Enabled the form to get parsed by the `Netlify Forms` for tracking and storing any submissions.
- Understood the in-built `Spam filter` feature of Netlify Forms. We have also added extra protection by adding a `honey-pot` field.
- Finally, enabled `notifications` such that we get e-mails when some users submit the form.

Exciting! Let us take it forward to integrate the `Fauna` to store the form data. Like before, you can refer to the source code from this repository, 

> {% github atapas/jamstack-subscription-form %}

# Set up the Fauna Data Store
`Fauna` is a secured transactional database available to access using the cloud API and GraphQL. It is flexible and straightforward to get started with an easy learning curve. To get started, we have first to create a database. After that, we need to supply a schema file to create the collection and documents for data.

## Create a Schema File
Create a folder with the name `db` at the root of the project folder. Create a schema file called `schema.gql` inside the `db` folder with the following content,

```shell
type Entry {
  fullName: String!
  email: String!
  frequency: String!
}

type Query {
  allEntries: [Entry!]!
}
```
It is a GraphQL file. We have defined a type, `Entry`, to map each of the form fields to the document properties in the database. We also define a query to return the list of entries that collect multiple form submissions.

## Set up Database
If you don't have an account with Fauna, you can register [from here](https://dashboard.fauna.com/accounts/register). Login to the Fauna dashboard and create a new database. Provide a database name and save.

![Create a Database](https://cdn.hashnode.com/res/hashnode/image/upload/v1620900027499/D0uVS2idt.png?border=1,CCCCCC&auto=compress)

Click on the `Security` option at the left panel of your database configuration. Next, create the server key to access the database.

![Create Security Token](https://cdn.hashnode.com/res/hashnode/image/upload/v1620900056669/hwjO0-x4Q.png?border=1,CCCCCC&auto=compress)

Please select the Role as `Server`. In addition, you can optionally provide a key name.

![Generate Key](https://cdn.hashnode.com/res/hashnode/image/upload/v1620900068319/LKGO4N7VZ.png?border=1,CCCCCC&auto=compress)

Please take a backup of the generated key into a file. We will use it soon.

![Server Key](https://cdn.hashnode.com/res/hashnode/image/upload/v1620902490768/9GAP-gm6e.png?border=1,CCCCCC&auto=compress)

## Import the Schema
Let us now import the schema to create collections and documents in the database. First, click on the `GraphQL` option from the left menu of the database configuration page. It will open up a playground asking you to import schema. Next, click on the `IMPORT SCHEMA` button and upload the `schema.gql` file.

![Import Schema](https://cdn.hashnode.com/res/hashnode/image/upload/v1620900096324/UP0gAHdrO.png?border=1,CCCCCC&auto=compress)

You will see a GraphQL code editor opens up to try out queries.

![GraphQL Code Editor](https://cdn.hashnode.com/res/hashnode/image/upload/v1620900107610/eGdw7SIMf.png?border=1,CCCCCC&auto=compress)

# Netlify Function to Store the Form Data
Now, we will write the code to store the subscription form data in the database. Create a file called `.env` at the root of the project folder with the following entry,

```shell
FAUNA_API_SECRET=<FAUNA_SERVER_ACCESS_KEY>
```
Please replace the `<FAUNA_SERVER_ACCESS_KEY>` with the key you have created while setting up the database.

> You must mention the .env file entry in your project's `.gitignore` file. It will make sure there is no accidental commit and push of the `.env` file to the git repository.

## Netlify Functions
[Netlify Functions](https://docs.netlify.com/functions/overview/) are serverless `lambda` functions managed by Netlify. We can trigger a Netlify Function when certain Netlify events occur. For example, when a form submission is verified, the event `submission-created` will occur, triggering a Netlify Function.

Create a folder `functions` at the root of the project folder. We will place all the `Netlify function` related code inside this folder. At this point, the project directory structure may look like this,

![Functions Folder](https://cdn.hashnode.com/res/hashnode/image/upload/v1620903882041/A4l5azuxM.png?border=1,CCCCCC&auto=compress)

## Install node-fetch
Now, let's create a function connected to the Fauna database and interact with it using the GraphQL queries. To do that, we need to make `XMLHTTPRequest`(Ajax Calls) from the function. We will use a light-weight library called, [node-fetch](https://www.npmjs.com/package/node-fetch) for this.

Using the command prompt, change the directory to the `functions` directory. Now use the following command to create the `package.json` file.

```shell
npm init -y
```
Now install `node-fetch` using this command,

```shell
yarn add node-fetch # or npm install node-fetch
```

## Create the Function
Create a file named, `submission-created.js` under the functions directory with the following content,

```js
const fetch = require("node-fetch");

exports.handler = async (event) => {
  const body = JSON.parse(event.body);
  const { email, fullName, frequency } = body.payload.data;

  const response = await fetch("https://graphql.fauna.com/graphql", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.FAUNA_API_SECRET}`,
    },
    body: JSON.stringify({
      query: `
        mutation($fullName: String!, $email: String!, $frequency: String!) {
            createEntry(data: { fullName: $fullName, email: $email, frequency: $frequency } {
            _id
            fullName
            email
            frequency
          }
        }      
      `,
      variables: {
        fullName,
        frequency,
        email,
      },
    }),
  })
    .then((res) => res.json())
    .catch((err) => console.error(err));

  return {
    statusCode: 302,
    headers: {
      Location: "success.html",
      "Cache-Control": "no-cache",
    },
    body: JSON.stringify({}),
  };
};
``` 
When a user submits the subscription form, Netlify will perform a form verification for spam. Once verified, it will trigger the `submission-created` event. Then, it will call the function automatically.

We get the form data using the body payload. Next, we make a `POST` call using the `fetch` method from `node-fetch`. Please notice, we use the GraphQL endpoint of Fauna and pass the required details in the query. Also, it is of type `mutation` and creates an `Entry` in the database.

# Run the Function Locally
Netlify needs a particular build configuration file called `netlify.toml` to inform the location of the Netlify functions. Create the netlify.toml file at the root of the project folder with the following content.

```shell
[build]
  functions = "functions"
```

We can run the function locally before deploying to Netlify. To do that, please install the Netlify Command Line Interface(CLI) tool globally.

```shell
npm install netlify-cli -g
```
After installing, run the following command from the root of the project folder,

```shell
netlify dev
```
Now, you can access the application @[localhost:8888](http://localhost:8888). Fill up the form and submit it. You should see the form data entry into the Fauna database.

![Data in fauna](https://cdn.hashnode.com/res/hashnode/image/upload/v1620905760778/oASN1OXpt.png?border=1,CCCCCC&auto=compress)

# Rest of the Configurations & Deploy
Let us now deploy the changes to Netlify. But, first, we need a do a few simple configuration changes to make this deployment work.

- Add the following `scripts` section in the main `package.json` file(the one at the root level of the project folder)

 ```js
  "scripts": {
    "functions": "cd functions && npm i && cd .."
  }
 ```
- Modify the `netlify.toml` file to include two more build configurations.

 ```shell
 [build]
  command = "npm run functions"
  publish = "src"
  functions = "functions"
 ```
 Here we additionally specify the command to set up the function, set up a base publish directory.

- Now, push all the code changes to your GitHub repository.
- Browse to the Netlify Interface for the project we have created in part-1 of the tutorial.
- Browse to the `Build & deploy` option and open up the `Environment` section.

 ![Environment in Netlify](https://cdn.hashnode.com/res/hashnode/image/upload/v1620572307323/yqW1B2qlF.png?border=1,CCCCCC&auto=compress)

- Add the Fauna Secret Key as the environment variable.

 ![Add Fauna Environment](https://cdn.hashnode.com/res/hashnode/image/upload/v1620572316486/OcfUQySH9O.png?border=1,CCCCCC&auto=compress)

- Trigger a Build.

That's it. We have deployed the form successfully with the Netlify function. [Here is a quick demo](https://youtu.be/UvDyIgfzNSs) of how the application works end-to-end.

{% youtube UvDyIgfzNSs %}

# In Summary
To Summarize,
- Created a form using `HTML`, `CSS`, and `Netlify Forms`.
- Enabled `Spam protection` using the `honey-pot` field.
- Enabled `e-mail` notifications.
- Set up a database with `Fauna` by uploading a GraphQL schema.
- We have utilized the `Netlify Function` to write the submitted and verified data to the database.
- Netlify Form submission triggers an event that enables us to trigger the `function` in turn.
- Everything works `serverless`, including the function.

<hr />
I hope you found the article insightful. If you enjoyed this article or found it helpful, let's connect. You can find me on [Twitter(@tapasadhikary)](https://twitter.com/tapasadhikary) sharing thoughts, tips, and code practices.

Do you know, you can support my work by sponsoring me? Please [check this out](https://blog.greenroots.info/sponsor).