Gatsby+Netlify CMSで音楽活動のポートフォリオを作った

1. 経緯

あくまで趣味の範囲だが、自分の音楽活動をまとめたページが欲しいなと思った。

関わった作品をまとめていればアピールしやすくなるし、何より実績として見える形にしておくと自信につながるからだ。

2. Gatsby+NetlifyCMSを採用した理由

WordPressで作る方法などもあったが、どれも自分には未知の世界だった。それならReactには馴染みがあるので、Reactつながりで話題のGatsbyに触れてみようと思ったのがきっかけだった。正直静的サイトジェネレータじゃなくても(ry

あとはブログっぽく更新が出来た方がいいので、NetlifyCMSで気軽に更新できるようにした。

3. 構築

Gatsbyのstarterを少しいじるだけで構築できる。

3-1. Gatsby

3-1-1. インストール

npm install -g gatsby-cli

で、Gatsbyのインストールができる。

gatsby new gatsby-starter-netlify-cms https://github.com/netlify-templates/gatsby-starter-netlify-cms

とし、テンプレートから制作を開始した。

あとはMarkdownにiframeを読み込むプラグインを入れる(Youtubeを埋め込んだりしたいので)。

npm i -S gatsby-remark-responsive-iframe

プラグインの設定をgatsby-config.jsから行う。

{
      resolve: `gatsby-transformer-remark`,
      options: {
        // CommonMark mode (default: true)
        commonmark: true,
        // Footnotes mode (default: true)
        footnotes: true,
        // Pedantic mode (default: true)
        pedantic: true,
        // GitHub Flavored Markdown mode (default: true)
        gfm: true,
        // Plugins configs
        plugins: [`gatsby-remark-responsive-iframe`],
      },
    },
    {

3-1-2. Markdownをページに変換する

Markdownファイルをページに変換するためにgatsby-node.jsを編集する。

// gatsby-node.js
/**
 * Implement Gatsby's Node APIs in this file.
 *
 * See: https://www.gatsbyjs.org/docs/node-apis/
 */

const _ = require('lodash');
const path = require('path');
const { createFilePath } = require('gatsby-source-filesystem');

// You can delete this file if you're not using it
exports.createPages = ({ actions, graphql }) => {
  const { createPage } = actions

  return graphql(`
    {
      allMarkdownRemark(limit: 1000) {
        edges {
          node {
            id
            fields {
              slug
            }
            frontmatter {
              title
              category
              templateKey
            }
          }
        }
      }
    }
  `).then(result => {
    if (result.errors) {
      result.errors.forEach(e => console.error(e.toString()))
      return Promise.reject(result.errors)
    }

    const posts = result.data.allMarkdownRemark.edges

    posts.forEach(edge => {
      const id = edge.node.id
      const templateKey = edge.node.frontmatter.templateKey;
      if(templateKey !== 'live-page'){
        createPage({
          path: edge.node.fields.slug,
          component: path.resolve(
            `src/templates/${String(templateKey)}.js`
          ),
          // additional data can be passed via context
          context: {
            id,
          },
        })
      }
    })

    let category = []
    posts.forEach((edge) => {
      if (_.get(edge, `node.frontmatter.category`)) {
        category = category.concat(edge.node.frontmatter.category)
      }
    })
    category = _.uniq(category)

    category.forEach((cat) => {
      const categoryPath = `/works/${cat}/`
        
      createPage({
        path: categoryPath,
        component: path.resolve(`src/templates/category.js`),
        context: {
          category: cat,
        },
      })
    })
  })
}

exports.onCreateNode = ({ node, actions, getNode }) => {
  const { createNodeField } = actions

  if (node.internal.type === `MarkdownRemark`) {
    const value = createFilePath({ node, getNode })
    createNodeField({
      name: `slug`,
      node,
      value,
    })
    const parent = getNode(node.parent)
  
    createNodeField({
      node,
      name: 'collection',
      value: parent.sourceInstanceName,
    })
  }
}

GraphQLで取得して、createPageでページを作成する。その際、frontmatterでどのページのものかを判別し、テンプレートを決定する。こうすることで、Markdownファイルをページとしてビルドできる。

また、works以下にバンドごとの一覧ページを作成するため、categoryでもcreatePageする。gatsby-starter-netlify-cmsのtagsの実装を参考に書いた。

3-1-3. テンプレートを作成する。

例えばworksのページだと以下のような感じ。

import React from 'react'
import { graphql } from 'gatsby'
import Layout from '../components/Layout'
import Cover from '../components/Cover'
import { HTMLContent } from '../components/Content'

export const WorksPostTemplate = ({title,content}) => {
    return (
        <Layout>
            <Cover>
                <h2>{title}</h2>
                <HTMLContent content={content}/>
            </Cover>
        </Layout>
    )
}

const WorksPost = ({data}) => {
  const { markdownRemark: post } = data;   
  return (
    <WorksPostTemplate title={post.frontmatter.title} content={post.html}/>
  )
}

export default WorksPost

export const pageQuery = graphql`
  query worksPost($id: String!) {
    markdownRemark(id: { eq: $id }) {
      html
      frontmatter {
        title
      }
    }
  }
`

3-2. NetlifyCMS

3-2-1. NetlifyCMSから更新するページ

NetlifyCMSから更新したいページはstatic/admin/config.yamlを編集して、Markdownの構造を記述する必要がある。

collections:
      - name: "works"
        label: "Works"
        folder: "src/pages/works"
        create: true
        slug: "{{year}}-{{month}}-{{day}}-{{slug}}"
        fields:
        - {label: "Template Key", name: "templateKey", widget: "hidden", default: "works-post"}
        - {label: "Title", name: "title", widget: "string"}
        - {label: "Publish Date", name: "date", widget: "datetime"}
        - {label: "Description", name: "description", widget: "string", required: false}
        - {label: "Body", name: "body", widget: "markdown"}
        - {label: "Category", name: "category", widget: "string"}
        - {label: "Image", name: image, widget: image, required: false}
        - {label: "ImageUrl", name: imageUrl, widget: string, required: false}

      - name: "live"
        label: "Live"
        folder: "src/pages/live"
        create: true
        slug: "{{year}}-{{month}}-{{day}}-{{slug}}"
        fields:
        - {label: "Template Key", name: "templateKey", widget: "hidden", default: "live-page"}
        - {label: "Title", name: "title", widget: "string"}
        - {label: "Publish Date", name: "date", widget: "datetime"}
        - {label: "Body", name: "body", widget: "markdown"}

      - name: "pages"
        label: "Pages"
        files:
          - file: "src/pages/info/index.md"
            label: "Info"
            name: "info"
            fields:
            - {label: "Template Key", name: "templateKey", widget: "hidden", default: "info-page"}
            - {label: "Title", name: "title", widget: "string"}
            - {label: "Body", name: "body", widget: "markdown"}
          
          - file: "src/pages/profile/index.md"
            label: "Profile"
            name: "profile"
            fields:
                - {label: "Template Key", name: "templateKey", widget: "hidden", default: "profile-page"}
                - {label: "Title", name: "title", widget: "string"}
                - {label: "Image", name: "image", widget: "image", required: false}
                - {label: "Body", name: "body", widget: "markdown"}

aboutページとprofileページは単一のページとしてpages以下に、worksページとliveページはブログポストページとしてそれぞれworksとliveに記述する。

4. 完成

https://yukigumo.netlify.app/

完成

ちなみに背景画像は以前撮った夕暮れの写真をSnapSeedというアプリでサクッと加工した。案外雰囲気は出たと思う。

5. まとめ

GatsbyはReactに触れたことがある人ならスムーズに開発を行えると感じた。ページのルーティングもそこそこ速い。難点があるとすればNetlifyCMSからの更新の反映に若干の遅延があることくらいだと思う。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA