gatsby-jsalpharetta
Presentation and Demo Project for https://www.meetup.com/JavaScriptAlpharetta/events/265017002/
Overview
Quick Start
Software You Need
MacOS Specific Prerequisites:
# Xcode Command line tools
xcode-select --install
# Homebrew
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
# Actual Dependencies
brew install node
brew install git
Windows Specific Prerequisites:
# Chocolatey
Set-ExecutionPolicy Bypass -Scope Process -Force; iwr https://chocolatey.org/install.ps1 -UseBasicParsing | iex
# Actual Dependencies
choco install nodejs
choco install git.install
Now, using a bash-compatible shell (e.g. Terminal on MacOS, Git Bash on Windows):
npm install -g gatsby-cli
gatsby new my-gatsby-site https://github.com/fabe/gatsby-starter-deck
cd my-gatsby-site
gatsby develop
Open localhost:8000 and Voilà!
Make a Change
- Edit
src/slides/01-intro.md
- Experience the magic of hot reload!
About Starters
Starters are boilerplate Gatsby sites.
A Tour of the Files
Gatsby Project Core Files
gatsby-config.js
Full Documentation: Gatsby Config API Docs and Data in Gatsby Tutorial
siteMetadata
Common bits of data to be reused accross the site.
Example use:
<Helmet
title={`${site.siteMetadata.title} — {site.siteMetadata.name}`}
/>
Helmet makes it easy to control content in the
<head>
plugins
Plugins are NodeJS packages that implement Gatsby Node APIs. Plugins can extend and modify virtually everything Gatsby does.
Typical usecases for plugins:
- Make external data or content available via GraphQL (files, databases, you-name-it)
- Transform data from various formats to JSON objects
- Inject third-party services (e.g. Google Analytics)
More
polyfill
- Exclude the default Promise polyfill.mapping
- Create foreign-key-like relationships between data sourcesproxy
- proxy unknown requests to the develop to a specified server
gatsby-node.js
Gatsby's "entry point" into generating your application. Export Gatsby function implementations to generate your app.
Project Structure
src/components
conventionally keeps our React components.src/pages
keeps the pre-defined pages of our app. Gatsby auto-generates a page perjs
file. Additional pages can be created using data and tempaltes.src/layouts
conventionally keeps our layout React components. Layouts are just React components that wrap other React components with common elements (e.g. header, footer, etc). Most folks keep their layouts in thesrc/components
folder (as recommended), but this is necessary forgatsby-plugin-layout
support.src/slides
project specific content to define our slides - this becomes queryable data thanks to thegatsby-source-filesystem
andgatsby-transformer-remark
plug-ins.src/templates
Layouts vs. Templates
Template components are for page types e.g. blog posts, slides, products. Layout components are for components shared across pages e.g. headers, footers, sidebars, etc.
Generally templates use layouts, but layouts don't use templates.
How it All Works
gatsby develop|build
- Gatsby reads
gatsby-config.js
and initializes the plug-ins. - Gatsby calls the functions exported from
gastby-node.js
exports.createPages
queries the markdown insrc/slides
- For each markdown file, we:
- Create nodes for each slide with
createNode
. Nodes are how data is modeled in Gatsby. This will make querying "slides" (rather than markdowns) easier later. - Create pages for each slide with
createPage
. Thecomponent
property tells Gatsby which template to use to render the page, in this casesrc/templates/slide.js
.
- Create nodes for each slide with
exports.sourceNodes
creates the GraphQL schema for our Slide objects.
When a Page is Created
// From gatsby-node.js
createPage({
path: `/${index + 1}`, // the path to the page
component: slideTemplate, // template to use
context: { // passed to props.pageContext
index: index + 1 // Used to query the slide
},
});
// From src/templates/slide.js
export default ({ data, transition }) => (
<div style={{'width': '100%'}}>
<div
style={transition && transition.style}
dangerouslySetInnerHTML={{ __html: data.slide.html }}
/>
</div>
);
export const query = graphql`
# $index is populated by context in the createPage call
query SlideQuery($index: Int!) {
# SlideQuery was defined in our sourceNodes function in gatsby-node.js ('type Slide...')
# Populate the "slide" property of the "data" property of props
slide(index: { eq: $index }) {
html
index
}
}
`;
More resources:
Just Enough React
React is a functional-style library (not a framework!) to produce web UIs. At it's core, React converts models (in the form of "state" and "props") to views.
Let's revisit part of the slide template:
// From src/templates/slide.js
// A function that takes in props...
export default ({ data, transition }) => (
// And returns a vew for those props
<div style={{'width': '100%'}}>
<div
style={transition && transition.style}
dangerouslySetInnerHTML={{ __html: data.slide.html }}
/>
</div>
);
More resources:
Just Enough GraphQL
A GraphQL service definines types, then provides functions to resolve each field on each type. In Gatsby,plug-ins define "nodes", which Gatsby can resolve in-memory, or custom resolvers for more advanced use cases.
We defined our type in gatsby-node.js
:
type Slide implements Node {
html: String
index: Int
}
And loaded them into memory by calling createNode
in gatsby-node.js
:
createNode({
id: createNodeId(`${node.id}_${index + 1} >>> Slide`),
parent: node.id,
children: [],
internal: {
type: `Slide`,
contentDigest: createContentDigest(html),
},
html: html,
index: index + 1,
});
We can then query the data in a way very similar to SQL:
// Query
allSlide {
edges { node { id, html, index } }
}
site {
siteMetadata {
date
name
title
}
}
// Output
{
"data": {
"allSlide": {
"edges": [
{
"node": {
"index": 1,
"html": "..."
}
},
// ...
]
},
"site": {
"siteMetadata": {
"date": "September 25, 2019",
"name": "James Tharpe",
"title": "JavaScript Alpharetta - Gatsby"
}
}
}
}
// Query
allSlide(filter: {index: {eq: 3}}) {
edges {
node {
html
index
}
}
}
// Output
{
"data": {
"allSlide": {
"edges": [
{
"node": {
"html": "\n<h1>🤫</h1>\n",
"index": 3
}
}
]
}
}
}
More resources:
The GraphiQL Explorer
Build a Portfolio Presentation from GitHub
Develop the Query
Go to the GitHub GraphQL Explorer and tweak your query.
Here's mine:
query {
user(login: "jamestharpe") {
repositories(first: 10, orderBy: { field: STARGAZERS, direction: DESC}) {
edges {
node {
description
name
forkCount
homepageUrl
stargazers { totalCount }
}
}
}
}
}
Next, install the gatsby-source-github
plug-in:
npm install gatsby-source-github --save-dev