Emma Wedekind
UX Engineer @ LogMeIn
@emmawedekind
https://wsvincent.com/what-is-a-static-site-generator/
Photo by Krisztian Tabori on Unsplash
receiveOrder(🌮);
cookMeat(🐮);
chopVegetables(🍅);
makeGuacamole(🥑);
assembleTaco(🌮);
makeCustomerHappy(😍);
cookMeat(🐮);
chopVegetables(🍅);
makeGuacamole(🥑);
assembleTaco(🌮);
...
receiveOrder(🌮);
makeCustomerHappy(😍);
npm install -g gatsby-cli
// gatsby new <project-name> <starter-repo-link>
gatsby new my-portfolio && cd my-portfolio
gatsby develop
├── src
│ ├── components
│ │ ├── header.js
│ │ ├── image.js
│ │ ├── layout.css
│ │ ├── layout.js
│ │ └── seo.js
│ ├── images
│ │ └── gatsby-icon.png
│ └── pages
│ ├── 404.js
│ ├── index.js
│ └── page2.js
├── gatsby-browser.js
├── gatsby-config.js
├── gatsby-node.js
└── ...
├── ...
├── src
│ ├── components
│ ├── pages
│ │ ├── 404.js
│ │ ├── index.js
│ │ ├── podcasting.js
│ │ ├── speaking.js
│ │ └── writing.js
│ └── templates
└── ...
/podcasting
/speaking
/writing
// pages/speaking.js
import React from "react"
import Layout from "../components/layout"
import SEO from "../components/seo"
const SpeakingPage = () => (
<Layout>
<SEO title="Speaking" />
<h1>I speak about things</h1>
</Layout>
)
export default SpeakingPage
// components/layout.js
import React from "react"
import PropTypes from "prop-types"
import { useStaticQuery, graphql } from "gatsby"
import Nav from "../components/nav";
import "./layout.css"
...
// components/layout.js
...
const Layout = ({ children }) => {
const data = useStaticQuery(graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
}
}
}
`)
...
// components/layout.js
...
return (
<div className='layout'>
<Nav />
<main className='main'>{children}</main>
</div>
)
}
Layout.propTypes = {
children: PropTypes.node.isRequired,
}
export default Layout
// pages/podcasting.js
...
const PodcastingPage = () => (
<Layout>
<SEO title="Podcasting" />
<h1>I podcast about things</h1>
</Layout>
);
export default PodcastingPage;
// components/nav.js
import React from "react";
import { Link } from "gatsby";
import "./nav.css";
...
...
const Nav = () => (
<nav className="nav">
<h3 className="nav__title">My Portfolio</h3>
<ul className="nav__list">
<li>
<Link
to="/" className="nav__link"
activeClassName="nav__link--active">
Home
</Link>
</li>
...
</ul>
</nav>
)
export default Nav;
activeClassName="iAmActive"
activeStyle={{ textDecoration: 'underline' }}
├── ...
├── src
│ └── components
│ ├── blogSquare.css
│ ├── blogSquare.js
│ ├── layout.css
│ ├── layout.js
│ ├── nav.css
│ ├── nav.js
│ └── seo.js
└── ...
// components/blogSquare.js
import React from 'react';
import { Link } from "gatsby";
import './blogSquare.css'
...
// components/blogSquare.js
...
const BlogSquare = ({ title, date, path, description }) => (
<section className="blogSquare">
<Link to={path} style={{
textDecoration: 'none',
color: '#4a4a4a'
}}>
<h2 className="blogSquare__title">{title}</h2>
<p className="blogSquare__date">{date}</p>
<p>{description}</p>
<p style={{ fontSize: '.8em', textDecoration: 'underline' }}>Read more</p>
</Link >
</section >
)
export default BlogSquare
├── ...
├── src
│ └── pages
│ ├── 2019-08-24-cute-cats
│ │ └── index.md
│ └── 2019-08-26-five-tech-skills-to-master
│ └── index.md
└── ...
// index.md
---
path: '/cute-cats'
date: '2019-08-24'
title: 'Cute Cats'
author: 'Me'
description: 'Here are some cute cat photos!'
---
![Cat under a blanket](https://images.unsplash.com/)
# Other fun markdown
## Woohoo!
├── ...
├── src
│ ├── components
│ ├── pages
│ └── templates
│ └── blogPost.js
└── ...
// templates/blogPost.js
export default function Template({ data }) {
const post = data.markdownRemark
return (
<Layout>
<Link
to="/writing"
style={{ ... }}
>
Back to blogs
</Link>
<h1
style={{ ... }}
>
{post.frontmatter.title}
</h1>
<h4
style={{ ... }}
>
Posted by {post.frontmatter.author} on {post.frontmatter.date}
</h4>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
</Layout>
)
}
https://michal.miskernik.sk/
yarn add gatsby-source-filesystem gatsby-transformer-remark
// gatsby-config.js
plugins: [
...
`gatsby-transformer-remark`,
{
resolve: 'gatsby-source-filesystem',
options: {
path: `${__dirname}/src/pages`,
name: 'pages',
},
},
http://localhost:8000/__graphql
// gatsby-node.js
const path = require('path')
exports.createPages = ({ boundActionCreators, graphql }) => {
const { createPage } = boundActionCreators
const postTemplate = path.resolve('src/templates/blogPost.js')
...
// gatsby-node.js
...
return graphql(`
{
allMarkdownRemark {
edges {
node {
html
id
frontmatter {
path
title
date
author
}
}
}
}
}
`).then(res => {...
// gatsby-node.js
...
if (res.errors) {
return Promise.reject(res.errors)
}
res.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: node.frontmatter.path,
component: postTemplate,
})
})
})
}
// templates/blogPost.js
import React from 'react'
import { Link, graphql } from 'gatsby'
import Layout from '../components/layout'
export default function Template({ data }) {
const post = data.markdownRemark
...
// templates/blogPost.js
export const postQuery = graphql`
query BlogPost($path: String!) {
markdownRemark(frontmatter: { path: { eq: $path } }) {
html
frontmatter {
date
path
title
}
}
}
`
https://gatsby-starter-blog-demo.netlify.com/
gatsby new my-blog-starter https://github.com/gatsbyjs/gatsby-starter-blog
@emmawedekind
By Emma Wedekind