Table of Contents
Gatsby Site Starterから始める
Start with a Template にアクセスしてみると、現在、静的サイトジェネレータ(SSG)のテンプレートが3つ選べます。
私はReactを書きたいのでGatsbyを選択しました。
あとはポチポチ押していくと1分足らずでGithubにPushされ、NetlifyにDeployされてブログが出来上がります。
/adminにアクセスすると管理側でのブログ投稿ができます。
管理側の認証はNetlify Identityが使われています。
記事がMarkdownで書けるのはうれしいですね。
アーキテクチャ
アーキテクチャは意外と単純で、
– 管理者認証にNetlify Identity (Git Gateway)
– 記事保存時に内容をMarkdownに変換しGithubへPush
– PushをトリガーにNetlifyが静的ページにBuild & Deployする
ブログはすでにコンテンツがレンダリングされた状態の静的ページをCDN経由で読み込むので、パフォーマンスが非常に良くなるということです。
[Gatsby] ブログ一覧ページをカスタマイズする
テンプレートにはAboutやProductページがあるので、関係するJSファイルはブログには必要ないので削除します。
とりあえず一覧ページをカスタマイズしてみます。
すでにCSS frameworkのBulmaが入っているのでそれを利用します。
まず先ほど作成したレポジトリからローカルにCloneします。
その後、
$ npm install
$ gatsby develop
すると開発サーバーが立ち上がりローカルで確認できます。
一覧ページの編集は src/pages/index.js で行います。
ソースコードをみるとJSXのコードとGraphQLでクエリを投げてデータを取得してきているがわかります。
これはMarkdownとして保存されている記事データを取得して表示しています。
どのようなクエリやデータが取れるかはGraphiQLツールを使って確認できます。
デフォルトでは localhost:8000/___graphql
へアクセスすると使えます。
![](/uploads/localhost_8000 ____ graphql-800x484.png)
以下のように変更してみました。
import React from "react";
import PropTypes from "prop-types";
import { Link, graphql } from "gatsby";
import Layout from "../components/Layout";
export default class IndexPage extends React.Component {
render() {
const { data } = this.props;
const { edges: posts } = data.allMarkdownRemark;
return (
<Layout>
<section className="section">
<div className="container">
<div className="content">
<h1 className="has-text-weight-bold is-size-2">Latest Stories</h1>
</div>
<div className="columns is-desktop is-multiline">
{posts
.map(({ node: post }) => (
<div className="column is-one-third" key={post.id}>
<div className="card">
<div className="card-image">
<figure className="image">
<img src={post.frontmatter.image} alt="post"/>
</figure>
</div>
<div className="card-content">
<div className="media">
<div className="media-content">
<p className="title is-4">
<Link className="has-text-primary" to={post.fields.slug}>
{post.frontmatter.title}
</Link>
</p>
<p className="subtitle is-6">Author: {post.frontmatter.author}</p>
</div>
</div>
<div className="content">
{post.excerpt}
<br/>
<Link className="button is-small" to={post.fields.slug}>
Keep Reading
</Link>
<br/>
<time>{post.frontmatter.date}</time>
</div>
</div>
</div>
</div>
))}
</div>
</div>
</section>
</Layout>
);
}
}
IndexPage.propTypes = {
data: PropTypes.shape({
allMarkdownRemark: PropTypes.shape({
edges: PropTypes.array
})
})
};
export const pageQuery = graphql`
query IndexQuery {
allMarkdownRemark(
sort: { order: DESC, fields: [frontmatter___date] },
filter: { frontmatter: { templateKey: { eq: "blog-post" } }}
) {
edges {
node {
excerpt(pruneLength: 400)
id
fields {
slug
}
frontmatter {
title
image
author
templateKey
date(formatString: "MMMM DD, YYYY")
}
}
}
}
}
`;
image や author などデフォルトにない項目がありますが、次で説明します。
[Netlify CMS] 管理側エディタ・ブログコンテンツをカスタマイズする
デフォルトでは画像などをブログに追加できませんでした。
項目を追加するためにいは static/admin/config.yml を編集します。
backend:
name: git-gateway
branch: master
media_folder: static/img
public_folder: /img
publish_mode: editorial_workflow
collections:
- name: "blog"
label: "Blog"
folder: "src/pages/blog"
create: true
slug: "{{year}}-{{month}}-{{day}}-{{slug}}"
fields:
- {label: "Template Key", name: "templateKey", widget: "hidden", default: "blog-post"}
- {label: "Title", name: "title", widget: "string"}
- {label: "Author", name: "author", widget: "string"}
- {label: "Publish Date", name: "date", widget: "datetime"}
- {label: "Description", name: "description", widget: "text"}
- {label: "Body", name: "body", widget: "markdown"}
- {label: "Tags", name: "tags", widget: "list"}
- {label: "Image", name: "image", widget: "image"}
上記のように設定することで、画像や著者名の項目を扱えるようになりました。
さらに、
publish_mode: editorial_workflow
を追加することで、
記事を保存していきなり投稿するのではなくて、 保存後にPull Requestが作られ、レビューしてもらってから投稿するような流れの切り替えをDnDで行えてしまいます。
設定した画像を使ってOGP対応する方法は
Gatsby + Netlify CMSで作ったブログをカスタマイズする
がとても参考になります。
最後に
Netlify CMSを使うことで驚くほど簡単にJAMStackなブログを作ることができました。
Gatsbyと使うことで見た目部分をReactで書くことができ、カスタマイズできてうれしいです。
NetlifyもNetlify CMSもまだまだカスタマイズできそうなので、これからも触っていきたいです。
個人的にはFusic Tech BlogもNetlify CMSを使ったりJAMstackで構築するのもありなのかなと思っています。