May 14th, 2019
Gatsby is a web framework for generating JAMStack-ready static files. It uses React for the front-end and GraphQL queries at build time for "content" (not-so-dynamic data). It's a cool new tech and a blog is a good use case for trying it out. Since my posts will be mostly programming related, I needed some features:
I like writing with Markdown
Syntax Highlighting is a must have.
Gatsby has a whole library of starters. Clone one to get started w/ a new project.
gatsby new gatsby-bootcamp https://github.com/gatsbyjs/gatsby-starter-hello-world
GraphQL playground by prisma is an improved GraphiQL (with dark theme!!) Only a few steps to enable it in Gatsby:
.env
file in root of project# .env
GATSBY_GRAPHQL_IDE=playground
npm i --save-dev env-cmd
"develop": "env-cmd .env gatsby develop",
npm i --save-dev gatsby-source-filesystem gatsby-transformer-remark
edit gatsby-config.json
:
plugins: [
{
resolve: "gatsby-source-filesystem",
options: {
name: "src",
path: `${__dirname}/src/`,
},
},
"gatsby-transformer-remark",
],
Markdown files in src
dir can now be queried w/ GraphQL:
{
allMarkdownRemark {
edges {
node {
id
frontmatter {
title
date
}
html
excerpt
fields { //
slug // comes from gatsby-node.js
} //
}
}
}
}
src/templates/blog.js
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
export const query = graphql`
query($slug: String) {
markdownRemark(fields: { slug: { eq: $slug } }) {
frontmatter {
title
date
}
html
}
}
`
export default ({ data }) => (
<Layout>
<h1>{data.markdownRemark.frontmatter.title}</h1>
<p>{data.markdownRemark.frontmatter.date}</p>
<div dangerouslySetInnerHTML={{ __html: data.markdownRemark.html }} />
</Layout>
)
Create new file gatsby-node.js
in root of project
const path = require("path")
module.exports.onCreateNode = ({ node, actions }) => {
const { createNodeField } = actions
if (node.internal.type === "MarkdownRemark") {
const slug = path.basename(node.fileAbsolutePath, ".md")
createNodeField({
node,
name: "slug",
value: slug,
})
}
}
module.exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const blogTemplate = path.resolve("src/templates/blog.js")
const res = await graphql(`
{
allMarkdownRemark {
edges {
node {
fields {
slug
}
}
}
}
}
`)
res.data.allMarkdownRemark.edges.forEach(edge => {
createPage({
component: blogTemplate,
path: `/blog/${edge.fields.slug}`,
context: {
slug: edge.fields.slug,
},
})
})
}
npm i gatsby-plugin-sharp gatsby-remark-images gatsby-remark-relative-images
gatsby-config.js
// plugins:
"gatsby-plugin-sharp",
{
resolve: "gatsby-transformer-remark",
options: {
plugins: [
"gatsby-remark-relative-images",
{
resolve: "gatsby-remark-images",
options: {
maxWidth: 750,
linkImagesToOriginal: false,
},
},
],
},
},
In source markdown file, specify path relative to the markdown file:

npm install --save node-sass gatsby-plugin-sass
React:
import styles from "./component.module.scss"
export default () => <h1 className={styles.header}>Hooray</h1>
component.module.scss
(same dir as component)
.header {
color: black;
}
npm install --save gatsby-remark-prismjs prismjs
// gatsby-config.js
// - plugins:
{
resolve: `gatsby-transformer-remark`,
options: {
plugins: [
`gatsby-remark-prismjs`,
]
}
}
// gatsby-browser.js
require("prismjs/themes/prism-okaidia.css")
// more themes @ https://github.com/PrismJS/prism/tree/master/themes