/pattern-buffer

My personal website, patternbuffer.io, written in gatsby, react, and go

Primary LanguageJavaScriptMIT LicenseMIT

PatternBuffer.io

My personal site where I write about fullstack/automation/embedded development, information theory, artificial intelligence, and just strikes my fancy as a professional nerd. The site is built on GatsbyJS, React, Go, & Python.

Notes

For an overview of the project structure please refer to the Gatsby Documentation

Development Environment

The page is built the normal way until linting, and the development server come into play. First, the project is started with the gatsby new PROJECT_NAME command. This bootstraps the project.

Then the project needs to be linted since coding in Javascript is so much more pleasant with it. This is done by installing eslint with the package manager yarn add --dev eslint. Then because the airBnB default linter configuration is a pretty great starting point, it became chosen after running npx eslint --init, which just runs the eslint initial configurator. Just choose "use popular eslint style config" and then choosing the AirBnB one.

This however reveals a few kinks with how Gatsby works apart from typical node/react based projects. Firstly, it will give linter errors concerning how JSX syntax is being used in a file with extension, *.jsx. This is addressed by adding this linter rule under the rules key of the linter configuration file: .eslint.json

    "rules": {
      "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }]
    }

Then, there is a much more complicated issue to deal with when using linters. Gatsby has internal dependencies to handling modules like react & prop-types. This is because gatsby is meant to use the react syntax, and architecture to create a static page generator with most of the benefits that react provides. This however creates a complication for modules that have to detect this dependency, because it isn't actually included in the node_modules or package.json. This will cause import/no-extraneous-dependencies linter errors because it doesn't know that although react & prop-types are imported, that they are handled internally by gatsby and not through imported node_modules. To fix this, there exists a set of linter rules that tell the linter that these are what's known as core-modules that tell the linter to ignore these so called "extraneous-dependencies".

Now, the linter should be working, and any other oddities can be handled later with the primary functionality mostly intact. Next are some problematic issues with the gatsby development server that is initiated by gatsby develop. First, the easier fix. The issue created for this project shows various investigations into why this happens, and it seems to relate to an internal issue with gatsby to how routes are defined relative to the host network. In short, specifying the --host option with localhost as the host route fixes the issues somewhat reliably.

Then is an even bigger issue which is that the gatsby development server doesn't detect file changes within the src/ directory and thus the primary feature of a development server is lost. Thanks to ahstro's comment on gatsby's issue #3043, he discovered that the project uses the node module chokidar to handle file watching, and that for some deeper reason I haven't investigated yet, requiring synchronous file watching can be enforced by setting environment variable, CHOKIDAR_USEPOLLING=1. With this in mind, and having tested the work arounds to gatsby develop a seperate script is added to the project's root ./dev-server that runs the gatsby development server with all the work arounds in one command:

./dev-server

#!/bin/bash
export CHOKIDAR_USEPOLLING=1
gatsby develop --host localhost

That takes care of the initial problems with developing a SASS site using my particular circumstances.

Main App Page

  • layouts/ contains the templates for laying out webpages than can be applied to pages
    • index.js is the main entry point
    • so is index.css as far as stylesheets are concerned
  • pages/ contains the subordinate pages that make the app
  • gatsby-config.js contains all of the gatsby configurations and references to used plugins

Adding the First Custom Page

  • To add page-3.js to represent a third page option, create the file: src/pages/page-3.js:
import React from "react";
import Link from "gatsby-link";

const ThridPage = () => (
  <div>
    <h1>Third Page</h1>
    <p>This is my first Gtasby site</p>
    <Link to="/page-2/">Back to Page 2</Link>
    <br />
    <Link to="/">Go back to the homepage</Link>
  </div>
);

export default ThridPage;
  • Pretty self-explanatory if already familiar with React
  • Next, make it so this page has a <Link> that references it in src/pages/index.js
import React from "react";
import Link from "gatsby-link";

const IndexPage = () => (
  <div>
    <h1>Hi people</h1>
    <p>Welcome to your new Gatsby site.</p>
    <p>Now go build something great.</p>
    <Link to="/page-2/">Go to page 2</Link>
    <br />
    <Link to="/page-3">New Page!</Link>
  </div>
);

export default IndexPage;

SASS Stylesheets

Gatsby can be enabled to use SASS instead of standard CSS as a preprocessor to create CSS with more nuanced syntax. There exists a gatsby plugin, gatsby-plugin-sass detailed on gatsby's plugin documentation to handle this. All that's really needed is to install the package gatsby-plugin-sass using either yarn or npm. Oddly they don't suggest that it should be a dev dependency so don't include the --dev option with yarn or the --save-dev option with npm. Then going into src/layouts/ there will be the entry-point for style sheets when gatsby compiles. This needs to be changed to a scss file, index.scss. Either by deleting the bootstrapped version and starting fresh or by rewritting it in either SASS or SCSS syntax. It's a really big file so, it is recommendable to simply start fresh and deleting its contents. Then to test whether it is working, set the background: property of body to be a nice ugly red, like below. And if it works, clearly the SASS preprocessor of gatsby-plugin-sass works. NOTE some *.js files in src/layouts will import the old ./index.css file, and its extension needs to be made index.scss.

src/layouts/index.scss

body {
  background: red;
}

To start things off, these are useful global values for a stylesheet to have. src/layouts/index.scss

$grey: #fafafa #f5f5f5 #eee #e0e0e0 #bdbdbd #9e9e9e #757575 #616161 #424242 #212121;
$grey-text: white white white white white black black black black black;

$button-font-size: 1.2rem;
$button-radius: 4px;

html {
  font-size: 62.5%;
}

body {
  background: nth($grey, 1);
  // background: red;
}

h1 { font-size: 3.2rem; font-style: bold; }
h2 { font-size: 2.4rem; font-style: bold; }
h3 { font-size: 2.4rem; }
h4 { font-size: 1.6rem; }
h5 { font-size: 1.2rem; }
h6 { font-size: 1.0rem; }

button {
  background: nth($grey, 9);
  border: 1px;
  border-radius: $button-radius; 
  box-shadow: none;
  color: nth($grey-text, 1);
  font-weight: 600;
  padding: 6px;
}

This is the typical main style settings that get used on my projects. Let's deconstruct some of them:

  • Although global variables should have their own _variables.scss partial SASS file, for starting things off it's useful to have them in the main or in this case index.scss file
  • Flat coloring of HTML elements is a good starting point for most projects except ones that specifically try to avoid it
    • Setting an array of 10 flatly colored grayscale values helps to keep things colored consistently from the get-go
    • Consider adding more color arrays as new colors are added
    • For now grayscale will do as varying grays are needed in almost any project
  • HTML font size is set at the root to font-size: 62.5% which has the effect of setting the scaling factor of fonts when using the rem relative unit to 10 virtual pixels on any display
    • This works on retina displays with upwards of 200PPI pixel density to the old 96 PPI standard that's been around since HTML's early days.
    • This sets a very intuitive standard of measure for the sizing of elements to a base 10 number
  • The default header elements are set to certain font sizes based on this newly normalized rem unit
  • Standard HTML buttons are almost always hideously ugly let's change that with some default styling

The react page after initial test pages and SASS

Now the page should look like this. The header tags could probably use some resizing but that can be handled later.

Building Gatsby Components Using React

Now that everything runs like a modern Node & React build/development environment (although under-the-hood it's a slightly different story) it's time to build some React components. A typical thing that most sites, especially blogs, will have is a header component. In this case it will also house a basic version of a navigation menu. For now, just a feed and about link.

To start things off, the freecodecamp guide has a section on creating NavBars using the bootstrapped Header component. Simply copying and pasting the added JSX code into the header adds some menus. There are some complications however, the linter is picking up jsx-a11y/anchor-is-valid errors. These come from the jsx-a11y eslint plugin included with the AirBnB linter style guide. And need to be investigated further. However, even though the menu links are sized horribly and only parts of them are visible in the header, it does work as expected with the three pages defined for testing <Links> as before. According to this issue on the eslint-plugin-jsx-a11y project, anything that generates <a> tags requires a valid href property linking another page or URI to it. React router doesn't quite work this way, and unfortunately the AirBnB style guide, though supposedly a very react friendly ruleset doesn't yet address this problem. To fix it add this rule for jsx-a11y/anchor-is-valid to the previous rules in the .eslintrc configuration and all should be well.

.eslint.json

    "rules": {
      "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
      "jsx-a11y/anchor-is-valid": [ "error", {
        "components": [ "Link" ],
        "specialLink": [ "to" ]
      }]
    }

Now since the Link component from gatsby-link doesn't throw linter errors, time to put together the basic first version of the Header and its Navigation section using Links. This will eventually be split into seperate components as I decide what the first release of the Header should look like. Below is the code, initially taken from freeCodeCamp's guide and then modified for my needs. That is to have a title for the site, and two Links, one leading to the main feed on the / route and the about page on /about. Without getting too serious about styling a few styles were changed to make the links reachable by the user and black is given as its background so that it stops looking like the gatsby bootstrap's rebeccapurple. Below is the code for this update, and the resulting page.

src/components/Header/index.js

import React from 'react';
import Link from 'gatsby-link';

const Header = () => (
  <div
    style={{
      background: 'black',
      marginBottom: '1.6rem',
    }}
  >
    <h1 style={{ color: 'white' }}>Pattern Buffer</h1>
    <div
      style={{
        margin: '0 auto',
        maxWidth: 960,
        padding: '3.2rem 1rem',
      }}
    >
      <ul style={{ listStyle: 'none', float: 'right' }}>
        <li style={{ display: 'inline-block', marginRight: '1rem' }}>
          <Link
            style={{
              color: 'white',
              textDecoration: 'none',
              fontSize: 'medium',
            }}
            to="/"
          >
            Feed
          </Link>
        </li>
        <li style={{ display: 'inline-block', marginRight: '1rem' }}>
          <Link
            style={{
              color: 'white',
              textDecoration: 'none',
              fontSize: 'medium',
            }}
            to="/about"
          >
            About
          </Link>
        </li>
      </ul>
    </div>
  </div>
);

export default Header;

Initial version of Header

Catch Links

Intercepts local links from markdown and other non-react pages and does a client-side pushState to avoid the browser having to refresh the page.

  • from GatsbyJS's docs describing the benefits of catch links

Because a lot of non-react built pages will be sourced to create pages, the catch links plugin will be useful to allow any generated pages from markdown for example to have the benefits of the native react parts of the site.

Sourcing & Transforming Markdown for Blog Posts

Using the official GatsbyJS guide to create a blog, the relevant plugins and configurations are going to be installed and configured. Source plugins in gatsby create nodes which are then transformed using transformer plugins to a usable format. In this case the source plugin that will be used is the gatsby-source-filesystem, which allows sourcing of files off the host filesystem to create nodes.

Install the plugin with yarn add gatsby-source-filesystem, then edit gatsby-config.js:

gatsby-config.js

module.exports = {
  // previous configuration
  plugins: [
    'gatsby-plugin-react-helmet',
    'gatsby-plugin-sass',
    'gatsby-plugin-catch-links',
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        path: `${__dirname}/src/pages`,
        name: 'pages',
      },
    }
  ]
}

Unlike other gatsby plugins that simply need to be included in the config to work, this one needs some configuration by setting up its own object entry inside the plugins: keyed array of plugins like above. The resolve key is there to resolve these configurations to the gatsby-source-filesystem plugin. options is where gatsby plugin options are specified. path defines the place to look for files in the host system. In this case in the project root vis-à-vis, ${__dirname}/src/pages, so the pages directory where other react-based pages have been created, like src/pages/index.js. Then name provides a name for the source and so it can be queried later using GraphQL to get the information therein.

Transforming a Source

Now with a source in place outside the native react pages that can be statically generated, it's possible to transform the new source into gatsby static pages as well. Here the filesystem source plugin will load file nodes (markdown files in this case) and then a new plugin will transform it into a static pages based off layout and stylesheets that query that data.

gatsby-transformer-remark uses remark as a markdown parser to transform markdown files into HTML. Moreover this transformer plugin can be made to take plugins to further extend the functionality. One such plugin that will be used later is for syntax highlighting of code blocks (gatsby-remark-prismjs), a plugin that copies linked files from markdown into the source tree (gatsby-remark-copy-linked-file), and also a plugin that compresses and adds by relative path referenced images within the markdown (gatsby-remark-images).

As any other plugin before, install using yarn or npm, whichever is preferred, yarn add gatsby-transformer-remark. Edit the gatsby-config.js with options like with gtasby-source-filesystem. Note that this time the only options is an empty array, which is left there for when associated plugins get added.

gatsby-config.js

// inside of the plugins array of gatsby-config.js
 {
    resolve: 'gatsby-transformer-remark',
    options: {
      plugins: [] // just in case those previously mentioned remark plugins sound cool :)
    }
  },
// other configs...

Using Sources & Transformers on a Blog Post

Now with all the plugins required to create markdown based posts, it's possible to create a test markdown file to start things off within src/pages as was specified as a place to query for markdown files. As a starting convention, YYYY-MM-DD-title will be the format for naming folders for each post. GatsbyJS isn't particularly picky about how these are named, but it might be about naming the main markdown file inside this folder index.md since it needs to know where to start parsing files. Note some research is needed to find out if index.md is requried.

src/pages/2018-01-14-hello-world/index.md

---
path: "/hello-world"
date: "2017-07-12T17:12:33.962Z"
title: "My First Gatsby Post"
---

Oooooh-weeee, my first blog post!

Remark adds the functionality of frontmatter to markdown files that gets parsed. Essentially all it is, is some syntax to add metadata to markdown files (or YAML, JSON, etc). Just surround the first part of a markdown file with a header like structure using --- dashes for the top and bottom bar of the frontmatter. Then inside can be specified different fields of metadata like, title, date, tag, category. These fields can then be queried by gatsby using GraphQL to change how the file is handled based on that metadata. For example, it will be useful to use all of those fields plus another, subtitle to create a preview for a post. path in this case creates a URL path that can be used, so if localhost:8000/hello-world will take you to this page, if it had a layout.

Creating a Page Template with React

Since gatsby is all about rendering using React components, in order to turn a markdown post into a page, a template written in react is needed first. Start by creating this file, src/templates/blog-post.js, keeping in mind that src/templates/ might need to be created first. The src/templates/ directory is a standard folder in gatsby for storing templates like this for any developer defined reused templates that get used by multiple pages.

src/templates/blog-post.js

import React from 'react';
import Helmet from 'react-helmet';

// import '../css/blog-post.scss'; // future styling

const pageTitle = 'Pattern Buffer';

// This will take among its props, an injected GraphQL query for blog posts
// TODO: Try different methods to replace dangerouslySetInnerHTML, like wrapping div
// TODO: Create proptypes
export default function Template({ data }) {
  const { markdownRemark: post } = data; // data.markdownRemark holds post data
  return (
    <div className="post__container">
      <Helmet title={`${pageTitle} - ${post.frontmatter.title}`} />
      <div className="post">
        <h1>{post.frontmatter.title}</h1>
        <div
          className="post__content"
          dangerouslySetInnerHTML={{ __html: post.html }}
        />
      </div>
    </div>
  );
}

export const pageQuery = graphql`
  query BlogPostByPath($path: String!) {
    markdownRemark(frontmatter: { path: { eq: $path } }) {
      html
      frontmatter {
        date(formatString: "MMMM DD, YYYY")
        path
        title
      }
    }
  }
`;

There is some magic at play here for anyone not accustomed to GraphQL and Gatsby. The Template is a prop injection handled by gatsby and it essentially becomes an injection of a component prop. <Template /> then needs to be seeded by a GraphQL query, one named pageQuery.

pageQuery gets used to with the injected data prop to query for pages and in the case of this template, frontmatter like title, path (for url resolution), date & finally the post content parsed by remark from the specific page. The main query performed by pageQuery gets named BlogPostByPath is injected with the current path (ie. the current url path of the page being rendered) as a parameter. Then the result of the query is a markdownRemark object which contains everything else needed to render the page.

markdownRemark is the injected property available as the prop data by destructuring in the Template component definition. There is a somewhat complex structure to accessing all the data desired within the markdownRemark query, but ultimately it's just setting up easy to access references for the body content of the post, and its frontmatter stored metadata. Any other accessible property of frontmatter that gets used to create blog post metadata can be added in along with the other properties. subtitle & previewImagePath will be added later to improve the blog.

NOTE: all the node based GraphQL queries take place at build time. The component is injected with the data prop that is seeded by the GraphQL query. Only if something dynamic (e.g. logic in componentDidMount, state changes, etc.) occurs this component gets processed as a react component which is then created as static rendered HTML, rendered through the React engine, GraphQL, & Gatsby together.

Querying for Posts

Gatsby uses its Node API which allows for creation of things like dynamic pages (blog posts) in this case, extending the babel or webpack configs, modifying the created nodes or pages, etc. The API is exposed in the ./gatsby-node.js file in the project root. Every export of found in this file gets parsed by Gatsby using the Node API. For creating a blog post, the only one of interest for now is the createPages part of the API. This is the code for the updated gatsby-node.js file, below.

./gatsby-node.js

const path = require('path');

exports.createPages = ({ boundActionCreators, graphql }) => {
  const { createPage } = boundActionCreators;

  const blogPostTemplate = path.resolve('src/templates/blog-post.js');

  return graphql(`{
    allMarkdownRemark(
      sort: { order: DESC, fields: [frontmatter___date] }
      limit: 1000
    ) {
      edges {
        node {
          excerpt(pruneLength: 250)
          html
          id
          frontmatter {
            date
            path
            title
          }
        }
      }
    }
  }`)
    .then((result) => {
      if (result.errors) {
        return Promise.reject(result.errors);
      }
      result.data.allMarkdownRemark.edges
        .forEach(({ node }) => {
          createPage({
            path: node.frontmatter.path,
            component: blogPostTemplate,
            context: {}, // additional data can be passed via context
          });
        });
    });
};

The createPages API is visibly accessed as an export. Then its generator function is accessed through the injected prop boundActionCreators and blogPostTemplate becomes the path to the location of the template for a blog post. Internally, Gatsby uses Redux to manage state, and boundActionCreators is simply the exposed ation creators of Gatsby, with createPage being the one specific to generating pages based off of Nodes.

GraphQL gets used once again to get all markdown nodes and making them accessible under allMarkdownRemark as a GraphQL property. Remember allMarkdownRemark was used before to define how data gets pulled from the Template to render the page from markdown. It's important to note that exports.createPages, the API expects a Promise to be returned, so it works seamlessly with the graphql function which expects a Promise. There are also regular callback API's inplace if that makes more sense.

In the future, as subtitles might be desirable for post previews, gatsby-plugin-remark exposes useful data like excerpt which is a short segment of text to be displayed as a preview, and id as a unique ID for the page.

This is only the query setup, then the resulting promise chain needs addressing, this is handled with .then. The posts are available by the path property result.data.allMarkdownRemark.edges. Each edge contains an internal node created by Gatsby used to construct a page. Note that the shape of this data is reflected both in this query and the one specified for the blog-post template. This data is then injected into the template's props. So to summarize, every time Gatsby builds, createPage is called, Gatsby creates a static HTML file of the path specified in the posts' frontmatter, then resulting in a string of the react component of the template specified which has props injected as the result of its GraphQL query.

Finally! Run yarn develop, gatsby develop, etc. to run the dev server and something like this should be the new result at http://localhost:8000/hello-world.

the first markdown generated blog post

Creating a Feed for Posts

Individual posts are only so useful by themselves. Better to have a listing or feed page to show them all so one can be chosen to be viewed in full. Gatsby has a standard for such listing pages. Since gatsby-source-filesystem has been specified with the location src/pages/ as the root of the page's filesystem it is there where an index.js file should exist that defines the root page, (ie the one that has no additional route in the URL). By default any page within pages is accessible by its file name without the extension.

src/pages/index.js

import React from 'react';
import Link from 'gatsby-link';
import Helmet from 'react-helmet';

// import '../css/index.css'; // add some style if you want!

export default function Index({ data }) {
  const { edges: posts } = data.allMarkdownRemark;
  return (
    <div className="blog-posts">
      {posts
        .filter(post => post.node.frontmatter.title.length > 0)
        .map(({ node: post }) => (
          <div className="blog-post-preview" key={post.id}>
            <h1>
              <Link to={post.frontmatter.path}>{post.frontmatter.title}</Link>
            </h1>
            <h2>{post.frontmatter.date}</h2>
            <p>{post.excerpt}</p>
          </div>
      ))}
    </div>
  );
}

export const pageQuery = graphql`
  query IndexQuery {
    allMarkdownRemark(sort: { order: DESC, fields: [frontmatter___date] }) {
      edges {
        node {
          excerpt(pruneLength: 250)
          id
          frontmatter {
            title
            date(formatString: "MMMM DD, YYYY")
            path
          }
        }
      }
    }
  }
`;

This uses another pageQuery using GraphQL as before to acquire the pages that are to be rendered as posts, and then constructs post previews using information like title, date, path. Note that excerpt gets used from remark's frontmatter property of that name. This is a short excerpt of the contents of the post, typically the first 140 characters or so. Later a subtitle frontmatter is to be created that allows for specifying a seperate preview that can be specified by the author if something else is desired to be viewed in preview. This will do just fine for now. Also note that Link gets used to route to the full post component whose path matches that of the markdown frontmatter property path.

Now there is an actually functional blog in place. New markdown posts will be rendered as new pages and listed in the index. The main functionality of this blog is now a template that can be further expanded on for most things that it needs to be capable, the rest is just React and SASS.

Index Layout

.
├── gatsby-config.js
├── package.json
└── src
    ├── html.jsx
    ├── pages
    │   ├── index.jsx
    │   └── posts
    │       ├── 01-01-2017
    │       │   └── index.md
    │       ├── 01-02-2017
    │       │   └── index.md
    │       └── 01-03-2017
    │           └── index.md
    ├── templates
    │   └── post.jsx
    │
    └── layouts
        └── index.jsx

In Gatsby there's a default folder structure whose behavior I hadn't considered before.layouts/index.jsx is an important layout component that I hadn't considered and just copied from some guide.

src/layouts/index.jsx (optional) wraps page components. You can use it for portions of pages that are shared across pages like headers and footers.

You can use the location prop to render conditionally based on the page URL.

That is taken from the Gatsby documentation's page on Building with Components. So essentially, by using this TemplateWrapper component, which has been updated to include my own components Header & BodyWrapper, every rendered page can be wrapped in a root layout that's common among all of them.

Content Wrapper

The ContentWrapper is the next most significant component after the TemplateWrapper. Since the TemplateWrapper is the main layout for every page that gets statically rendered by Gatsby, it's going to need other components that manage the shared layout and components that get shared by every rendered page. Since a sidebar is going to be rendered conditionally based on either the width of the browser (sidebar is always visible) and the state of a toggled input to slide ContentWrapper to the left to reveal a Sidebar component.

To make this easier, ContentWrapper is created to standardize the space of the page where page content gets rendered, Sidebar becomes the conditionally rendered navigation and dynamic menu based on the current page. Initially, this effect was done by having TemplateWrapper simply not render Sidebar when the menuVisible state is false. With all the flexbox work done so far, the layouts at rest look fine, but it kills the illusion of sliding the users' perspective to right to look at a sidebar because the ContentWrapper simply shrinks the its contents to make room for the Sidebar. To improve this, later, give BodyWrapper negative margins to make room for Sidebar, but to do that Sidebar needs a standardized size and ideally a more organized stylesheet so that will wait till then.

Bulma UI

A great CSS/SASS/React stylsheet framework I'm growing increasingly fond of is Bulma. Named after Bulma from Dragonball Z of course, why I'm not entirely sure, but her teal hair color is clearly a favorite of the developers'. It's a large UI framework, not a Semantic or Material sized one, but it's getting up there, so I'll go into each feature as I arrive at it. Here I'll just go over the way that it gets integrated and has its SASS variables customized for this site, or any Gatsby site that should use it.

First download the npm package, npm install --save bulma. Then, I created a file, ./src/styles/bulma-composed.scss, where all sass styles will be composed into the index.scss file used for all global stylesheet parameters. Then import bulma-composed.scss into index.scss. In bulma-composed.scss:

src/styles/bulma-composed.scss:

// Initial Variables
@import "~bulma/sass/utilities/initial-variables";
@import "~bulma/sass/utilities/functions";

// Redefine initial color values provided by bulma
$red: #ff5252;
$orange: #ff793f;
$yellow: #ffb142;
$green: #33d9b2;
$blue: #34ace0;
$purple: #40407a;

// Add my own color definitions
$red-dark: #b33939;
$orange-dark: #cd6133;
$yellow-dark: #cc8e35;
$green-dark: #218c74;
$blue-dark: #227093;
$purple-dark: #2c2c54;
$lavender: #706fd3;
$lavender-dark: #474787;

$black: hsl(0, 0%, 4%);
$black-bis: hsl(0, 0%, 7%);
$black-ter: hsl(0, 0%, 14%);
$grey-darker: hsl(0, 0%, 21%);
$grey-dark: hsl(0, 0%, 29%);
$grey: hsl(0, 0%, 48%);
$grey-light: hsl(0, 0%, 71%);
$grey-lighter: hsl(0, 0%, 86%);
$white-ter: hsl(0, 0%, 96%);
$white: hsl(0, 0%, 100%);

// Inversions
$red-invert: findColorInvert($red);
$red-dark-invert: findColorInvert($red-dark);
$orange-invert: findColorInvert($orange);
$orange-dark-invert: findColorInvert($orange-dark);
$yellow-invert: findColorInvert($yellow);
$yellow-dark-invert: findColorInvert($yellow-dark);
$green-invert: findColorInvert($green);
$green-dark-invert: findColorInvert($green-dark);
$blue-invert: findColorInvert($blue);
$blue-dark-invert: findColorInvert($blue-dark);
$purple-invert: findColorInvert($purple);
$purple-dark-invert: findColorInvert($purple-dark);
$lavender-invert: findColorInvert($lavender);
$lavender-dark-invert: findColorInvert($lavender-dark);

// // Color aliases
$primary: $purple;
$primary-invert: $purple-invert;
$info: $blue;
$info-invert: $blue-invert;
$success: $green;
$success-invert: $green-invert;
$warning: $yellow;
$warning-invert: $yellow-invert;
$danger: $red;
$danger-invert: $red-invert;
$light: $white-ter;
$dark: $grey-darker;

//TODO: Include font family definitions

// Add to the color map
@import '~bulma/sass/utilities/derived-variables';
$addColors: (
    "link-color": ($primary, $primary-invert),
);
$colors: map-merge($colors, $addColors);

@import '~bulma';

The important bits are the initial imports of ~/bulma/sass/utilities/Initial-variables & insert the imports and the adding of color values to $colors at the end ar what allows developers to use bulma styles but with their own customisations.

New Layouts

TODO Expand on this with new layouts refactor Layouts beyond what is typically discussed in React, Gatsby considers through a folder src/layouts/ as shared react components that manage common layout between each rendered markdown page. So think Sidebars and Headers.

References

  1. Gatsby documentation - Building with Components
  2. freeCodeCamp: Setting Up a Getting Used to Gatsby
  3. Github: eslint-plugin-import - documentation including imports/core-modules rule
  4. Project Issues: Gatsby develop updating & disconnection issue
  5. Github/gatsbyjs/gatsby: issue #3043
  6. GatsbyJS Docs: gatsby-plugin-sass
  7. Github Issues: eslint-plugin-jsx-a11y #340
  8. GatsbyJS Docs: Creating a blog with GatsbyJS
  9. GatsbyJS Docs: gatsby-plugin-catch-links
  10. GatsbyJS Docs: gatsby-transformer-remark
  11. Github: woorm/remark
  12. GatsbyJS Docs: Node API Specification
  13. GatsbyJS Docs: Building with Components
  14. Bulma Docs: Main Page