npm package: @mkitio/gatsby-theme-blog
Description: A Gatsby blog theme with rich MDX support by MK IT https://mkit.io
Author: MK IT Ltd.
Latest version: 1.0.1

# @mkit/gatsby-theme-blog

> A Gatsby blog theme with rich MDX support by MK IT https://mkit.io

**Feel free to [submit improvements, bug reports and PRs](<(https://gitlab.com/mkit/open-source/gatsby-theme-blog/issues)>).**

**Any planned changes or improvements will be listed in the theme's [ROADMAP.md](./ROADMAP.md).**

## Description

A Gatsby blog theme supporting local filesystem content, MDX, image processing, and content mapping.

The theme provides several built-in features to set the bare-minimum for building a blog including:

- Content sourcing and transformation from the filesystem via [`gatsby-source-filesystem`](https://www.gatsbyjs.org/packages/gatsby-source-filesystem/?=gatsby-source-file) and [`gatsby-transformer-yaml`](https://www.gatsbyjs.org/packages/gatsby-transformer-yaml/?=gatsby-transformer-yaml)
- [MDX support](https://mdxjs.com/) via [`gatsby-plugin-mdx`](https://www.gatsbyjs.org/packages/gatsby-plugin-mdx/)
- Image processing via [`gatsby-plugin-sharp`](https://www.gatsbyjs.org/packages/gatsby-plugin-sharp/?=gatsby-plugin-sharp) and [`gatsby-remark-images`](https://www.gatsbyjs.org/packages/gatsby-remark-images/?=gatsby-remark-image)
- Auto creation of individual blog post pages
- Auto mapping of frontmatter fields to YAML configuration files
- Auto slug field generation via [`createFilePath`](https://www.gatsbyjs.org/packages/gatsby-source-filesystem/#createfilepath)
- Auto [reading-time](https://www.npmjs.com/package/reading-time) field generation

What you'll get:

- Content sourced from the local filesystem, e.g. `content/` folder within your repository
- Blog post pages created automatically given your `content/posts/` contents
- Auto blog post slug field generation based on folder naming, e.g. `content/posts/mypost` results in `/mypost` slug
- Reading time field based on the content length of the MDX file, e.g. `{ text: '1 min read', minutes: 1, time: 60000, words: 200 }`
- MDX support out of the box
- Optimized images out of the box
- Ability to define relations between `frontmatter` fields and your own mappings, e.g. multiple authors, tags, etc.
- Blank canvas for you to built on top of, i.e. pages and components are for you to implement.

Heavily inspired by [`gatsby-theme-blog`](https://www.gatsbyjs.org/packages/gatsby-theme-blog/) and [`gatsby-theme-blog-core`](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-theme-blog-core).

## Install

### Manually add to your site

```sh
# with npm
npm install --save mkit@gatsby-theme-blog

# or with yarn (recommended)
yarn add mkit@gatsby-theme-blog
```

## Usage

### Theme options

| Key           | Default value                                 | Description                                                                                                                                            |
| ------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `contentPath` | `content/`                                    | The location where your content and mappings live. Should be on the root level of your project.                                                        |
| `mapping`     | `{ 'Mdx.frontmatter.author': 'AuthorsYaml' }` | Optional mapping between node types, i.e. frontmatter to YAML relations. [Read more.](https://www.gatsbyjs.org/docs/gatsby-config/#mapping-node-types) |

### Example usage

```js
// gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: '@mkit/gatsby-theme-blog',
      options: {
        // defaults to `/content`
        contentPath: '/my-content'
        // defaults to author mapping only
        mapping: {
          'Mdx.frontmatter.author': 'AuthorsYaml',
          'Mdx.frontmatter.tags': 'TagsYaml'
        }
      }
    }
  ]
}
```

### How to Content

Content lives under the `contentPath/posts` location on the root level of your project. Typically that's `content/posts/` by default.

The plugin will automatically detect any `.mdx` files and create pages on the root URL of your site, e.g. `localhost:8000/__EXAMPLE__`. See `content/posts/__EXAMPLE__` for more details.

_If you don't have such folder structure already, this theme will automatically create it for you and include useful examples._

```sh
# content/
.
├── mappings
└── posts                       # blog posts
    └── __EXAMPLE__               # example post folder used for auto slug generation
        ├── images                # blog post images or assets
        │   ├── 150.png
        │   ├── 1500x500.png
        │   ├── 3000x1000.png
        │   ├── 300x600.png
        │   └── 500.png
        └── index.mdx             # blog post .mdx
```

### How to Mapping

You may want to reuse or define multiple complex objects in your blog post's frontmatter. For instance you may want to add an author to your post's frontmatter but the author itself should have its own properties such as name, bio, avatar, etc. That's where mapping kicks in.

It is possible to define whatever relations you need between your `.mdx`'s frontmatter and `YAML` definitions. See `content/mappings/authors` for more details.

Mapping between node types is possible thanks to [Mapping node types in Gatsby](https://www.gatsbyjs.org/docs/gatsby-config/#mapping-node-types).

```sh
# content/
.
├── mappings                    # [optional, enabled by default] all available mappings
│   └── authors
│       ├── authors.yaml          # authors definition
│       └── images                # [optional] author avatar images
│           └── john-doe.png
└── posts
```

### How to GraphQL

**Nodes of Interest**

The theme and its configuration adds several node types available to query via GraphQL. You can see the details at `localhost:8000/__graphql`'s Explorer.

- `allFile` and `file`
- `allMdx` and `mdx`
- `allAuthorsYaml` and `authorsYaml`

#### All blog posts

Typically you'd want to get get all blog posts so you can build your "posts" page. The page where all posts are displayed in some way.

```graphql
# GraphQL query to get all blog posts
query allPosts {
  allMdx {
    edges {
      node {
        frontmatter {
          title
        }
      }
    }
  }
}
```

Results in:

```js
// Data returned by the query
{
  "data": {
    "allMdx": {
      "edges": [
        {
          "node": {
            "frontmatter": {
              "title": "Welcome To Your Blog"
            }
          }
        }
      ]
    }
  }
}
```

#### Frontmatter

Frontmatter fields defined in your `.mdx` files can act as meta data for your posts. By default the blog post has title and author.

```graphql
# GraphQL query to get all blog posts with frontmatter and author mapping
query allPosts {
  allMdx {
    edges {
      node {
        frontmatter {
          title
          author {
            id
            slug
            image {
              relativePath
            }
          }
        }
      }
    }
  }
}
```

Results in:

```js
// Data returned by the query
{
  "data": {
    "allMdx": {
      "edges": [
        {
          "node": {
            "frontmatter": {
              "title": "Welcome To Your Blog",
              "author": {
                "id": "John Doe",
                "slug": "john-doe",
                "description": "Consectetur aliqua mollit commodo cillum eiusmod ullamco nisi in.",
                "image": {
                  "relativePath": "mappings/authors/images/john-doe.png"
                }
              }
            }
          }
        }
      ]
    }
  }
}
```

#### Fields

```graphql
# GraphQL query to get all blog posts with auto-generated fields by the theme
query allPosts {
  allMdx {
    edges {
      node {
        fields {
          slug
          readingTime {
            minutes
            text
            time
            words
          }
        }
      }
    }
  }
}
```

Results in:

```js
// Data returned by the query
{
  "data": {
    "allMdx": {
      "edges": [
        {
          "node": {
            "fields": {
              "slug": "/__EXAMPLE__",
              "readingTime": {
                "minutes": 3.315,
                "text": "4 min read",
                "time": 198900,
                "words": 663
              }
            }
          }
        }
      ]
    }
  }
}
```