Thein's Logo

Using Airtable As Database With Netlify Functions

Jan 01, 20214 mins read
banner post image

I have been exploring serverless functions for awhile. Then, I found out about Netlify functions which is very easy to implement for beginners like me. I decided to build a simple form submission for my audience to say hi from my personal webpage. I would like to share how I implemented Netlify Function and using Airtable as database.

Installing netlify-cli

First, let install netlify-cli on our machine. If you already have netlify-cli, you can skip this step and go to next section. You can install globally via npm by

$ npm i -g netlify-cli

We can use the following commands to verify that we have installed successfully:

$ netlify --help # Or "ntl --help" for shorter syntax
Netlify command line tool

VERSION
  netlify-cli/3.4.2 win32-x64 node-v12.18.2

USAGE
  $ netlify [COMMAND]

COMMANDS
  addons     (Beta) Manage Netlify Add-ons
  api        Run any Netlify API method
  build      (Beta) Build on your local machine
  deploy     Create a new deploy from the contents of a folder
  dev        Local dev server
  env        (Beta) Control environment variables for the current site
  functions  Manage netlify functions
  help       display help for netlify
  init       Configure continuous deployment for a new or existing site
  link       Link a local repo or project folder to an existing site on Netlify
  login      Login to your Netlify account
  open       Open settings for the site linked to the current folder
  plugins    list installed plugins
  sites      Handle various site operations
  status     Print status information
  switch     Switch your active Netlify account
  unlink     Unlink a local folder from a Netlify site
  watch      Watch for site deploy to finish

Add netlify.toml file

Second, we need to add netlify.toml file under the root of the application project. This is going to tell Netlify where our serverless functions are.

# Inside netlify.toml
[build]
  functions = "functions"

Create sayhi serverless functions

Next, create a new serverless function locally by using hello-world function template:

$ ntl functions:create sayhi
? Pick a template
  ----[JS]----
> [hello-world] Basic function that shows async/await usage, and response formatting
  [apollo-graphql] GraphQL function using Apollo-Server-Lambda!
  [apollo-graphql-rest] GraphQL function to wrap REST API using apollo-server-lambda and apollo-datasource-rest!
  [auth-fetch] Use `node-fetch` library and Netlify Identity to access APIs
  [create-user] Programmatically create a Netlify Identity user by invoking a function
  [fauna-crud] CRUD function using Fauna DB
(Move up and down to reveal more choices)

You will see newly created serverless functions under functions/sayhi/sayhi.js

// Docs on event and context https://www.netlify.com/docs/functions/#the-handler-method
const handler = async (event) => {
  try {
    const subject = event.queryStringParameters.name || 'World'
    return {
      statusCode: 200,
      body: JSON.stringify({ message: `Hello ${subject}` }),
      // // more keys you can return:
      // headers: { "headerName": "headerValue", ... },
      // isBase64Encoded: true,
    }
  } catch (error) {
    return { statusCode: 500, body: error.toString() }
  }
}

module.exports = { handler }

Run the serverless function locally

We can run our sayhi serverless function on our localhost by using:

$ ntl dev
◈ Netlify Dev ◈
◈ Functions server is listening on 64128
◈ Starting Netlify Dev with gatsby
◈ .. snip ..

It will take a few seconds to spin up the local server. Once it is done, you can navigate to http://localhost:8888/.netlify/functions/sayhi

{"message":"Hello World"}

Then, you will see the response in your browser.

Optional: Add redirect for severless function

This is optional. I want to change the route name into /api/sayhi instead of /.netlify/functions/sayhi. To do that, we have to add redirection inside netlify.toml file:

[build]
  functions = "functions"

[[redirects]]
  from = "/api/*"
  to = "/.netlify/functions/:splat"
  status = 200

After this, we need to stop Netlify development server and start ntl dev again. Now we have scaffolded our sayhi serverless function. Next, we are going to configure and setup Airtable.

Creating new base in Airtable

If you do not have any Airtable account yet, you can create a free account at airtable.com. If you already have it, let's create new base for our database from the scratch. I will name it sayhi

Create new base in airtable
New base with default fields

You will see the standard columns (Name, Notes and etc.) in our newly created base. Since we are building something like contact form for our sayhi function, we will delete the default column and create:

  • Primary field: timestamp (as Date format)
  • name (as Single Line Text)
  • email (as Email format)
  • subject (as Single Line Text)
  • message (as Long Text)

Add new fields to our base

Create Airtable API Key and Base ID

Navigate to your account overview to create Airtable API key. You can also read through the Airtable API documentation for more details. We can get our base ID inside the documentation.

Get Airtable API key
Get Airtable Base ID

Install official Airtable JavaScript library

We need to install airtable.js as our npm package dependency by:

$ npm i airtable@latest

Create POST methods for our sayhi API endpoint

First, we need to initialize the Airtable base connection configurations. Then, we configure the table name. In this case, I am storing Airtable's API key, base id and table name in environment variables. We will only allow POST method in this example. name, email, subject and message will be in request body.

The following is the code for our sayhi.js functions and you can edit it according to your need:

const Airtable = require("airtable")

const handler = async (event) => {
// Configure Airtable base connection
const base = new Airtable({ apiKey: process.env.AIRTABLE_API_KEY }).base(
  process.env.AIRTABLE_BASE_ID
)

// Configure table name
const table = base(process.env.AIRTABLE_TABLE_NAME)

  try {
    const { httpMethod } = event
    let body = bodyParse(event.body)
    const { name, email, subject, message } = body
    const date = new Date()

    // Only allow POST
    if (httpMethod !== "POST") {
      return {
        statusCode: 405,
        body: JSON.stringify({ message: "Method Not Allowed" })
      }
    } else if (!name || !email || !subject || !message) {
      return {
        statusCode: 400,
        body: JSON.stringify({ message: "Bad Request" })
      }
    }

    // Create record
    // NOTE: Without `await`, this will not wait until data has been inserted into Airtable and return Status 202 due to async behaviour.
    // As a result, we will receive 202 response code but our data are not inserted into our Airtable base.
    await table
      .create({
        timestamp: date.toISOString(),
        name,
        email,
        subject,
        message
      })
      .then((rec) => {
        console.log("Successfully inserted into airtable")
      })
      .catch((err) => {
        throw err
      })
    return {
      statusCode: 202,
      body: JSON.stringify({ message: "Accepted" })
    }
  } catch (error) {
    return { statusCode: 500, body: "Oops! Something went wrong." }
  }
}

const bodyParse = (body = {}) => {
  try {
    let b = JSON.parse(body)
    return b
  } catch {
    return {}
  }
}

module.exports = { handler }

I use Postman to verify the code works and return correct response code to the client. Make sure ntl dev is running while testing via Postman. The data from the request body will save into Airtable database.

Data inserted into Airtable

Conclusions

We have implemented our sayhi serverless function. If you are building different kind of forms, you can also explore Netlify Forms as an alternative. It will be more simple approach. You get the idea.

Hope you learn something new today.

More readings