# getting AT data to a website!
## the steps
if you don't have node, git and gatsby installed, check out [these instructions](https://www.gatsbyjs.com/docs/tutorial/part-zero/) to get your machine ready for development. If you just have node and git, enter `npm install -g gatsby-cli` to install the `gatsby-cli`
start up a gatsby project with
```
cd ~/Development
gatsby new my-gatsby-project
cd my-gatsby-project
code .
gatsby develop
```
Then go to [localhost:8000](http://localhost:8000) to see if it's working.
In your code editor, let's get rid of all the default gatsby pages except the index, so delete all of the files in `/src/pages` except `index.js` (alternatively, you could throw them all in a folder called `/reference/gatsby` if you want to be able to reference them later on.
We are mainly going to emphasize getting the airtable data in for this tutorial, so we'll actually start by doing that.
Let's install the airtable plugin:
```
npm i gatsby-source-airtable
```
Then let's add it to our `gatsby-config.js`, something like
```
{
resolve: "gatsby-source-airtable",
options: {
apiKey: process.env.AIRTABLE_API_KEY,
tables: [
{
baseId: process.env.AIRTABLE_BASE_ID,
tableName: "MyTable",
},
]
}
},
```
you'll need to store your environment variables in a `.env.development` file:
```
AIRTABLE_API_KEY=keyxxxxxxxxxxxxx
AIRTABLE_BASE_ID=appxxxxxxxxxxxxx
```
then you'll need to pull these environment variables in to `gatsby-config.js` with `dotenv`. So install it with `npm i dotenv` and then add the following lines at the top of `gatsby-config.js`
```
require("dotenv").config({
path: `.env.${process.env.NODE_ENV}`,
})
```
now that you've done this, you should be able to stop the server, then run `gatsby develop` and see the Airtable data show up in [GraphiQL](http://localhost:8000/___graphql)
## MAKING AN INDEX OF RECORDS
something like this:
```
/** @jsx jsx */
import { jsx } from 'theme-ui'
import { graphql } from "gatsby"
export default ({data}) => {
const allAirtableData = data.allAirtable.edges;
return (
<div
sx={{padding: "4em"}}
>
{/* <pre>
{JSON.stringify(allAirtableData, null, 4)}
</pre> */}
{
allAirtableData.map(({node}) => (
<div
sx={{width: "100%", textAlign: "center"}}
>
<a href={`/yokai/${node.recordId}`}
sx={{
// color: "rgba(0,0,30,.9"
}}
><h1
sx={{
fontFamily: "Avenir Next, sans-serif",
fontSize: "3em",
fontWeight: "900",
color: "rgba(0,0,30,.9)",
textDecoration: "none"
}}
>{node.data.Name}</h1></a>
</div>
))
}
</div>
)
}
export const query = graphql`
query {
allAirtable {
edges {
node {
id
recordId
data {
Description
mainFeature
Creator
Link_to_Project
secondFeature
Name
weight
type
mainAttack
region
specialAttack
height
backgroundColor
foregroundColor
canvaCardLink
canvaCardBack {
id
thumbnails {
large {
url
width
height
}
}
}
canvaCardFront {
id
thumbnails {
large {
url
width
height
}
}
}
}
}
}
}
}
`
```
## CREATING INDIVIDUAL PAGES
To create a page per record, we'll need to add to our `gatsby-node.js` file.
maybe something like this?
```
const { createFilePath } = require(`gatsby-source-filesystem`)
const path = require(`path`)
exports.onCreateNode = ({ node, getNode, actions }) => {
const { createNodeField } = actions
if (node.internal.type === `Mdx`) {
console.log(`found mdx node of type ${node.internal.type}`)
const fileNode = getNode(node.parent)
const slugStem = createFilePath({ node, getNode })
const slugRoot = fileNode.sourceInstanceName
? fileNode.sourceInstanceName
: "content"
createNodeField({
node,
name: `slug`,
value: `/${slugRoot}${slugStem}`,
})
createNodeField({
node,
name: `pageType`,
value: slugRoot,
})
createNodeField({
node,
name: `title`,
value: node.frontmatter.title || fileNode.name || "no title",
})
createNodeField({
node,
name: `mainImage`,
value: node.frontmatter.mainImage || "/gatsby.jpg",
})
}
}
exports.createPages = async ({ graphql, actions, reporter }) => {
const { createPage } = actions
const mdxResult = await graphql(`
query {
allMdx {
edges {
node {
id
fields {
slug
title
pageType
}
headings(depth: h1) {
value
}
}
}
}
}
`)
if (mdxResult.errors) {
reporter.panicOnBuild('🚨 ERROR: Loading "createPages" query')
}
const mdx = mdxResult.data.allMdx.edges
mdx.forEach(({ node }, index) => {
console.log(
`creating page for id ${node.id} with slug ${node.fields.slug} with initial h1 of ${(node.headings && node.headings[0]) ? node.headings[0].value : "no h1"}`
)
createPage({
path: node.fields.slug,
component: path.resolve(
`./src/templates/test-layout.js`
),
context: { id: node.id },
})
})
const yokaiResult = await graphql(`
query {
allAirtable {
edges {
node {
id
recordId
}
}
}
}
`)
if (yokaiResult.errors) {
reporter.panicOnBuild('🚨 ERROR: Loading "yokai" query')
}
const yokai = yokaiResult.data.allAirtable.edges
yokai.forEach(({ node }, index) => {
console.log(
`creating page for id ${node.id} with slug /yokai/${node.recordId} `
)
console.log(JSON.stringify(node, null, 4))
createPage({
path: `/yokai/${node.recordId}`,
component: path.resolve(
`./src/templates/yokai-template.js`
),
context: { recordId: node.recordId },
})
})
}
```
as you can guess, this is for a specific type of Airtable record, so you'll have to tweak it a bit. It also requires you to have a page-template that you use, referenced in this little chunk:
```
createPage({
path: `/yokai/${node.recordId}`,
component: path.resolve(
`./src/templates/yokai-template.js`
),
context: { recordId: node.recordId },
})
```
here's what's in our `yokai-template.js` (which appears to need `theme-ui`, which you can add with `npm i theme-ui`)
```
/** @jsx jsx */
import { jsx } from 'theme-ui'
import YokaiFlip from "../components/yokai-flip.js"
export default ({ data }) => {
return (
<div
sx={{
width: "80%",
margin: "auto",
padding: "2em",
}}
>
<div
sx={{
width: "100%",
textAlign: "center"
}}
>
<h1
sx={{
fontFamily: "Avenir Next, sans-serif",
fontWeight: "900",
fontSize: "4em"
}}
>{data.airtable.data.Name}</h1>
</div>
<YokaiFlip
front={ data.airtable.data.canvaCardFront ? data.airtable.data.canvaCardFront[0].thumbnails.large.url : data.airtable.data.cleanImageJPG ? data.airtable.data.cleanImageJPG[0].thumbnails.full.url : "/_images/gatsby.jpg"}
back= { data.airtable.data.canvaCardBack ? data.airtable.data.canvaCardBack[0].thumbnails.large.url : data.airtable.data.cleanImageJPG ? data.airtable.data.cleanImageJPG[0].thumbnails.full.url : "/_images/gatsby.jpg"}
/>
<div
sx={{
height: "300px"
}}
></div>
{/* <pre>{JSON.stringify(data, null, 4)}</pre> */}
</div>
)
}
export const query = graphql`
query GetRecord($recordId: String!){
airtable(recordId: { eq: $recordId}) {
id
table
recordId
data {
Description
mainFeature
Creator
Link_to_Project
secondFeature
Name
weight
type
mainAttack
region
specialAttack
height
backgroundColor
foregroundColor
canvaCardLink
canvaCardBack {
id
thumbnails {
large {
url
width
height
}
}
}
canvaCardFront {
id
thumbnails {
large {
url
width
height
}
}
}
cleanImageJPG {
thumbnails {
full {
url
}
}
}
}
}
}`
```