<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Sethu Sathyan🏡</title>
    <description>The latest articles on Forem by Sethu Sathyan🏡 (@sethu).</description>
    <link>https://forem.com/sethu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F387539%2F95d533f7-2892-403b-a22c-7445353431cb.jpg</url>
      <title>Forem: Sethu Sathyan🏡</title>
      <link>https://forem.com/sethu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/sethu"/>
    <language>en</language>
    <item>
      <title>How to build a website using Gatsby &amp; Airtable in 30 mins</title>
      <dc:creator>Sethu Sathyan🏡</dc:creator>
      <pubDate>Mon, 18 May 2020 14:55:05 +0000</pubDate>
      <link>https://forem.com/sethu/how-to-build-a-website-using-gatsby-airtable-in-30-mins-42gm</link>
      <guid>https://forem.com/sethu/how-to-build-a-website-using-gatsby-airtable-in-30-mins-42gm</guid>
      <description>&lt;p&gt;We all love Airtable for various reasons and use cases. In these times of COVID, we have seen many websites built using Airtable to solve different issues. Popular ones include &lt;a href="https://candor.co/hiring-freezes"&gt;candor.co&lt;/a&gt;, etc..&lt;/p&gt;

&lt;p&gt;Airtable has a killer feature &lt;a href="https://support.airtable.com/hc/en-us/articles/205752117-Creating-a-base-share-link-or-a-view-share-link"&gt;"share view"&lt;/a&gt;, where you can share the view of your table and embed it on your website using a simple iframe. I have also used the same feature for building the first version of &lt;a href="https://www.startupsvscovid.com"&gt;Startups vs COVID&lt;/a&gt; - a live repository of funds, support &amp;amp; resources for startups tackling COVID-19.&lt;/p&gt;

&lt;p&gt;A simple HTML website with the Airtable iframes which looked like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_WXxyYGV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/j6hwtk8woacvc41kawtj.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_WXxyYGV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/j6hwtk8woacvc41kawtj.JPG" alt="First version of website"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But here are some of the drawbacks of this version:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No way to share/highlight individual records&lt;/li&gt;
&lt;li&gt;Lack of SEO&lt;/li&gt;
&lt;li&gt;Unable to track analytics of each record&lt;/li&gt;
&lt;li&gt;Unable to share individual records on social&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To solve this problem, a second version of the platform was built using Gatsby and Airtable without any iframes.&lt;/p&gt;

&lt;p&gt;And here is the second/current version:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--czk6Z22h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/muy94p38znm0ks65kyr3.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--czk6Z22h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/muy94p38znm0ks65kyr3.JPG" alt="Modified version of website"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Why Gatsby?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Love for React&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Previously built &lt;a href="http://leapcode.io/"&gt;Leapcode&lt;/a&gt; using React and &lt;a href="https://nextjs.org"&gt;nextjs&lt;/a&gt; and my &lt;a href="http://sethusathyan.in/"&gt;personal website&lt;/a&gt; using Gatsby.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automatic static pages generator&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Blazing fast website &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Faster deployment using Netlify&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PWA and faster page load&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Plugin library&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  How to build the website using GatsbyJs &amp;amp; Airtable?
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;In this article, we'll focus only on connecting airtable &amp;amp; displaying data on your gatsby web page. We are not going deeper into the design of the website here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First, install GatsbyJS and start a project. &lt;a href="https://www.gatsbyjs.org/tutorial/"&gt;Here&lt;/a&gt; is how you can do it. You can also use one of the &lt;a href="https://www.gatsbyjs.org/starters/?v=2"&gt;starter packs&lt;/a&gt; to get started.&lt;/p&gt;

&lt;p&gt;Gatsby has several plugins that will help you integrate with different apps. Here we are going to take advantage of the &lt;em&gt;gatsby-source-airtable&lt;/em&gt; plugin; it sources data into the website from the Airtable base. It is a prewritten module that uses airtable API to convert to Gatsby GraphQL.&lt;/p&gt;

&lt;p&gt;Once your Gatsby website &amp;amp; the Airtable base is ready, install the &lt;code&gt;gatsby-source-airtable&lt;/code&gt; plugin in your folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# using npm
npm install --save gatsby-source-airtable

# using yarn
yarn add gatsby-source-airtable
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Get Started
&lt;/h4&gt;

&lt;p&gt;Here is how the folder will look once you finish building:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q8Dzksxq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/a5rkpb25f5nv5tjnuv0g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q8Dzksxq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/a5rkpb25f5nv5tjnuv0g.png" alt="Folder structure"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Integrating Airtable to your code&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once you have installed &lt;code&gt;gatsby-source-airtable&lt;/code&gt; plugin, configure your Airtable tables in the &lt;code&gt;gatsby-config.js&lt;/code&gt; file as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gatsby-source-airtable&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AIRTABLE_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;tables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;baseId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YOUR_AIRTABLE_BASE_ID&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YOUR_TABLE_NAME&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Airtable API key - This can be found in the Airtable on Help→API Documentation. You should inject your API key using an environment variable instead of using it directly in the file.&lt;/li&gt;
&lt;li&gt;The base ID of your base can be found in the API Documentation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, we are using only one table. You can add as many tables you want and should specify that inside the tables in &lt;code&gt;gatsby-config.js&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Getting data from Airtable to our Gatsby Project
&lt;/h4&gt;

&lt;p&gt;Gatsby uses GraphQL to send data to different pages. The plugin &lt;code&gt;gatsby-source-airtable&lt;/code&gt; will convert Airtable's REST APIs to GraphQL schemas.&lt;/p&gt;

&lt;p&gt;Let's start by checking if you are getting data from the Airtable API using the GraphQL interface Gatsby has.&lt;/p&gt;

&lt;p&gt;Start your gatsby server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gatsby develop
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Go to your: &lt;code&gt;http://localhost:5000/_graphql&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, let's run a simple query to check the data from the Airtable. &lt;code&gt;gatsby-source-airtable&lt;/code&gt; provides a query called &lt;code&gt;allAirtable&lt;/code&gt;, which will fetch all the data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;allAirtable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;edges&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;column_name_1&lt;/span&gt;
                &lt;span class="nx"&gt;column_name_2&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At this point, we have got the airtable connected, and the data should be coming to the GraphQL. Next step is to bring this data to our homepage which is &lt;code&gt;pages/index.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gatsby&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;allAirtableData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;allAirtable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;allAirtableData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;column_name_1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;column_name_2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recordId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Click&lt;/span&gt; &lt;span class="nx"&gt;Here&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/a&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="s2"&gt;`
    query {
        allAirtable {
            node {
           recordId
            data {
                    column_name_1
                    column_name_2
            }
            }
        }
    }
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That was simple! We mapped the list from the &lt;code&gt;allAirtable&lt;/code&gt; query to the &lt;code&gt;data&lt;/code&gt; variable in the react component. Then we iterated the list using &lt;code&gt;map()&lt;/code&gt; and listed all the data from the airtable base.&lt;/p&gt;

&lt;h4&gt;
  
  
  Creating standalone pages for each record
&lt;/h4&gt;

&lt;p&gt;To improve the SEO, creating pages for each row felt like a good idea, but we didn't want to create it manually for every single row; instead, we wanted to automatically generate these pages when the Airtable updates. The best way to do this is to run the whole project on a backend server and route using the server-side rendering. But Gatsby offers an inbuilt function to create pages with gatsby builds. That was a big time saver for us. We didn't have to maintain a backend server to run our website.&lt;/p&gt;

&lt;p&gt;Before we begin, let's start by creating a standard template for that page.&lt;/p&gt;

&lt;p&gt;Create a new folder "template" and create a file called &lt;code&gt;post.js&lt;/code&gt; inside that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;airtable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;column_name_1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;airtable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;column_name_2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="s2"&gt;`
query GetRecord($recordId: String!){
    airtable(recordId: { eq: $recordId}) {
        id
        table
        recordId
        data {
            column_name_1
            column_name_2
        }
    }
}`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;On a quick look, the GraphQL query became a bit complex, but it's relatively easy. There is a new variable &lt;code&gt;$recordId&lt;/code&gt;, which is basically the id of each row/record in the airtable; the value of &lt;code&gt;recordId&lt;/code&gt; would be passed from a script (we will be doing it in the next step) and would be used to fetch the corresponding record from the airtable.&lt;/p&gt;

&lt;h4&gt;
  
  
  Introducing the createPage function
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;createPage()&lt;/code&gt; is an inbuilt function in gatsby to create pages on the build programmatically. Now, all we have to do is, get all the records from the airtable, iterate through each record, and create pages for each one.&lt;/p&gt;

&lt;p&gt;To begin, we need to create a new file, &lt;code&gt;gatsby-node.js&lt;/code&gt;, on the root folder with the following content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`path`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createPages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createPage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
        {
        allAirtable {
          edges {
            node {
              table
              recordId
              data {
                column_name_1
                column_name_1
              }
            }
          }
        }
      }
    `&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// For each path, create page and choose a template.&lt;/span&gt;
    &lt;span class="c1"&gt;// values in context Object are available in that page's query&lt;/span&gt;
    &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;allAirtable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;edges&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;createPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recordId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`./src/template/post.js`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;recordId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recordId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Step by step process of what is happening in this page&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run a graphQL query with &lt;code&gt;allAirtable&lt;/code&gt;. This will fetch every row from the airtable base and store it in a constant called &lt;code&gt;result&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Iterate through each array inside &lt;code&gt;result.data.allAirtable.edges&lt;/code&gt;, which is basically each record in the airtable base&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;createPage()&lt;/code&gt; will now generate pages with path &lt;code&gt;/:recordId&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;It will use the component as the template for each page. Here we specified it as &lt;code&gt;post.js&lt;/code&gt;, which we created before this.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;context&lt;/code&gt; will send the &lt;code&gt;recordId&lt;/code&gt; to the template which we used in the graphQL query in &lt;code&gt;post.js&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Voila! Let's do a gatsby deploy again to see individual records in a new page. You can type the URL with any &lt;code&gt;recordId&lt;/code&gt; → eg: &lt;code&gt;localhost:5000/rec2312321413&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Congrats! Now you have all the data that you need from the Airtable base in your frontend. There is a lot more you can do with this, such as working with multiple tables, webhooks for Airtable, components for your frontend, PWA, etc. Stay tuned for the next article to know more about how to implement these.&lt;/p&gt;

&lt;p&gt;Thank you so much for reading. Leave a comment if you have any questions or suggestions!&lt;/p&gt;

</description>
      <category>gatsby</category>
      <category>airtable</category>
      <category>graphql</category>
      <category>react</category>
    </item>
  </channel>
</rss>
