ElmstaticとNetlifyCMSでブログを作ろう

14 min read読了の目安(約13100字

概要

Elmstaticという静的サイトジェネレーターを使って自分だけのブログを作ろう!という記事です。

静的サイトジェネレーターの良さ

いちいちHTMLを書かなくても、Markdownで記事を書くことでWebページを作成できるのが良いです。ブログには最適だと思います。

Elmstaticの良さ

Gatsbyなど静的サイトジェネレーターは他にもたくさんありますが、Elmstaticを使うとElmでWebページを作ることができますので、elm-uiを使って簡単にページのレイアウトができたり、動的なWebページを手軽に作れたりします。

Elm用の静的サイトジェネレーターは他にもあります。詳しくはElm向けの静的サイトジェネレータを使ってみよう!をご覧ください。

Elmstaticのセットアップ

Elmstaticの公式サイトのHow to use itに書かれている手順に従ってセットアップします。

手順の大まかな内容

  1. npmでElmstaticをインストールする
  2. Elmstatic用のディレクトリを作り、その中でelmstatic initを実行してElmstaticで使用するファイル群を生成する
  3. elmstatic buildを実行してHTMLを生成する
  4. 生成されたファイル一式は_siteフォルダに格納される
  5. http-serverコマンドで_siteフォルダの中身をローカルのWebサーバーで表示する
  • 手順の中にelmstatic init --elm-markupというコマンドがありますが、これは実行しなくて良いです。
  • 手順の最後にあるhttp-serverを実行したときにcommand not foundとなる場合はnpm install -g http-serverでインストールしてください。

すべての手順を実行してhttp://127.0.0.1:8080をブラウザで開き、以下のような画面が表示されたら成功です!

オリジナルの記事を投稿してみよう

_postsフォルダの中に.mdファイルがあります。これがブログの記事ファイルです。初期状態で入っているファイルをコピーして新しいファイルを作り、記事を投稿してみましょう。

コピーコマンドの例
cp 2019-01-02-another-post.md 2021-04-14-firstpost.md
記事ファイルのフォーマット
---
title: 記事タイトル
tags: 記事につけるタグ
---
ここにMarkdownで記事を書きます

ファイル名の規則

Elmstaticの公式サイトの_postsの説明に書かれている通り、以下のケバブケースでファイル名をつけてください。
YYYY-MM-DD-任意の文字列.md

.mdファイルが出来上がったら

cd ..で_postsフォルダの1つ上に戻り、elmstatic buildでビルドして、http-server _siteでサーバーを起動してブラウザで表示してみます。初期設定ではトップページが記事一覧のページになっているので、トップページに記事が増えたことが確認できると思います。もし記事が増えていないときはブラウザでページを再読み込み(更新・リロード)してみてください。

ファイル名を未来の日付にすると、その日が到来するまでは投稿されません。もし未来日付のファイルもすぐに投稿したいときは、ビルドするときにオプション-dを指定します。
elmstatic build -d

Netlifyへのデプロイ

ローカル環境で記事を投稿できたならば、NetlifyにデプロイしてWebに公開してみましょう。手順はElmstaticの公式サイトのDeploying via Netlifyに記載されている通りです。

手順の大まかな内容

  1. Elmstaticのセットアップ手順の中で作ったmysiteフォルダをGithubで管理する必要があります。私はあまりgitの扱いが上手ではないので他の記事を参考にしていただいた方が良さそうですが、一応私がやっている手順を書いておきます。
私のgit操作手順
  • mysiteフォルダでgit init
  • Githubで新規リポジトリを作成
  • ターミナルで以下のコマンドを実行
    git remote add origin GithubリポジトリのClone用URL
    GithubリポジトリのClone用URLはGithubリポジトリでCodeボタンを押すと表示されます。ファイルが何もなくCodeボタンが表示されていないときはQuick setup欄に表示されます。
  1. .gitignoreに_siteを書いておきます。_siteに生成後のHTMLが入っているのですが、Netlifyにデプロイするときに自動的にビルドするようにNetlifyに設定するので、_siteフォルダは不要なのです。同じ理由でelm.jsも不要。私の場合は.gitignoreが以下の内容になりました。
_site
elm-stuff
elm.js
  1. 編集した.gitignoreも含めた全てのファイルをcommitし、Githubのリポジトリにpushします。
私のgit操作手順
  • git add .
  • git commit . -m "任意のコミットメッセージ"
  • git branchをするとローカルのbranch名が表示されます。リモートのbranch名がmainでローカルのbranch名masterになっているなど、branch名が合っていないときは以下のコマンドでリモートに合わせます。(リモートbranch作成時にREADME.mdや.gitignoreを作成していないならば不要な手順です)
    git branch -m master main
  • git pull origin main --allow-unrelated-histories でリモートbranchの内容をマージ(リモートbranch作成時にREADME.mdや.gitignoreを作成していないならば不要な手順です)
  • git push origin mainなどのbranch名 でリモートbranchにpush
  1. NetlifyNew site from Gitボタンを押して、Githubリポジトリと連携させ、サイトを作成します。
  • Build commandには以下を指定します。
    npm i -g elm@latest-0.19.1 && npm i -g elmstatic && elmstatic build -d
    (-dは前述の通り未来日付の記事を投稿するためのオプションです)
  • Publish directoryには_siteを指定します。

これでブログがWebに公開されます。記事を投稿したいときは、Githubのリポジトリの_postsフォルダに.mdファイルを増やしてください。自動的にNetlifyにデプロイされます。

(任意)Netlifyの設定

URLが自動生成された意味不明なものになっていますが、NetlifyのSite settingsDomain managementにあるCustom domainsOptionsEdit site nameで任意のサブドメイン名を設定できます。

Elmstaticの設定

Elmstaticの公式サイトのconfig.jsonの説明にある通り、Elmstaticの設定はconfig.jsonに書かれていますので、自分のサイトに合うように書き換えます。

tags

"tags": ["other", "software"]という行は注意が必要です。ここに列挙したタグ以外を記事(.md)に指定すると、elmstatic buildのときにエラーとなります。この制約をなくしたい場合はこのtagsの行を削除します。

copy

初期状態では以下のようになっています。この設定により、https://negiboudu-blog.netlify.app/のようにルート階層にアクセスしたときでもhttps://negiboudu-blog.netlify.app/postsというふうにpostsフォルダを参照するようになります。

"copy": {
    "/posts": "/"
},

feed

RSS feedの設定のようですが、私はよくわかっていないので解説できません!ごめんなさ〜い。

config.jsonの全体

私の場合は以下の内容となりました。これがうまく機能しているのかはわかりませんが、とりあえず書いておきます。

config.jsonの内容
{
    "siteTitle": "ねぎぼうづぶろぐ",
    "outputDir": "_site",
    "copy": {
        "/top": "/"
    },
    "feed": {
        "type": "rss",
        "title": "ねぎぼうづぶろぐ",
        "description": "ついったーに書くには少し長い文章はこちらに書こうかと思います。",
        "id": "https://negiboudu-blog.netlify.app",
        "link": "https://negiboudu-blog.netlify.app/posts",
        "image": "https://negiboudu-blog.netlify.app/img/logo.png",
        "copyright": "Copyright: negiboudu",
        "language": "ja",
        "generator": "Elmstatic",
        "author": {
            "name": "negiboudu",
            "link": "https://negiboudu-blog.netlify.app/about"
        }
    }
}

Elmstaticのデフォルトのページを編集する

色々とElmstaticのデフォルトのページ内容となっているので、自分のサイトに合った内容に書き換えてみましょう。いきなりガラっと書き換えるよりは、少しずつ書き換えていった方がわかりやすいと思います。書き換えた内容をWebに公開したいときは、Githubリポジトリにpushすれば自動的に公開されます。

_layouts/Page.elm

全ページで共通して使われているページレイアウトが書かれています。GithubやTwitterへのリンクがあったりするので、自分のアカウントの内容に書き換えてみましょう。

Page.elm内にはmarkdownという関数があり、その中でgithubFlavoredという値を設定しています。これを設定すると、Markdown内の改行などの扱いがGithubと同じようになるのだと思います(私は未検証ですがTrueにしています)。詳細が気になる方はElmのMarkdownパーサーelm-explorations/markdownのドキュメントをご確認ください。

_pages/About.md、Contact.md

Elmstaticではブログのような投稿するタイプのページだけでなく、自己紹介などの固定のページもMarkdownで作成できます。デフォルトではAbout.mdとContact.mdが該当します。自由に書き換えてみてください。

その他のファイル

Elmstaticのファイル構成がElmstaticの公式サイトに書かれていますので、それを参照しながら色々書き換えてみてください。

NetlifyCMSの設定

概要

NetlifyCMSとは、ヘッドレスCMSと呼ばれるものの1つです。これを使うと、いちいちGithubに記事ファイルをcommitしなくても、Webの画面上で記事(.md)を作成して投稿できます。

設定方法

NetlifyCMSのドキュメントを参照しながら設定します。ちょっとわかりづらいところがあるので解説します。

フォルダとファイルの追加

NetlifyCMSで使用する管理画面を用意する必要がありますので、_resources/フォルダの中にadminフォルダと下記の2ファイルを追加します。Elmstaticの静的なファイルは_resources/フォルダに置くとそのままトップの階層にデプロイされます。

_resources/
  admin/
    config.yml
    index.html

_resources/admin/index.htmlの編集

NetlifyCMSのドキュメントのサンプルそのままで大丈夫です。

index.htmlの内容
<!doctype html>
<html>
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Content Manager</title>
</head>
<body>
  <!-- Include the script that builds the page and powers Netlify CMS -->
  <script src="https://unpkg.com/netlify-cms@^2.0.0/dist/netlify-cms.js"></script>
</body>
</html>

_resources/admin/config.ymlの編集

NetlifyCMSのドキュメントを見ると色々書いてあってちょっとわかりづらいです。私は以下のように書いてうまく動きました。

config.ymlの内容
backend:
  name: git-gateway
  branch: master # Branch to update (optional; defaults to master)

media_folder: "_resources/img/uploads"

collections:
  - name: "blog" # Used in routes, e.g., /admin/collections/blog
    label: "Blog" # Used in the UI
    folder: "_posts" # The path to the folder where the documents are stored
    create: true # Allow users to create new documents in this collection
    slug: "{{year}}-{{month}}-{{day}}-{{slug}}" # Filename template, e.g., YYYY-MM-DD-title.md
    fields: # The fields for each document, usually in front matter
      - {label: "Title", name: "title", widget: "string"}
      - {label: "Tags", name: "tags", widget: "string"}
      - {label: "Body", name: "body", widget: "markdown"}
  • branchには自分のブランチ名(masterとかmainとか)を書いてください。
  • fieldsの内容は、記事ファイル(.md)の冒頭の内容と一致させるようです。

認証の設定

Enable Identity and Git Gatewayに従って、NetlifyCMSの管理画面に自分だけがログインできるように設定します。手順の中に登場するIdentity > Registrationの設定はEdit settingsボタンを押してInvite onlyにしてください。Githubなどアカウントでの1-clickログインを有効にしたい場合はExternal providersのAdd providerから設定します。Services > Git GatewayはEnableにするだけでOKです。

認証ウィジェットの追加

Add the Netlify Identity Widgetに従って設定します。

_layouts/Elmstatic.elmのhtmlTemplate関数に以下の行を追加します。

, script "//identity.netlify.com/v1/netlify-identity-widget.js"

以下のスクリプトの呼び出しも設定しておく必要があります。

<script>
  if (window.netlifyIdentity) {
    window.netlifyIdentity.on("init", user => {
      if (!user) {
        window.netlifyIdentity.on("login", () => {
          document.location.href = "/admin/";
        });
      }
    });
  }
</script>

手順ドキュメントを見ると、メインのインデックスページに設定するように書かれています。しかしElmstaticのページはElmで生成しているので、設定がすんなりできそうにありません。よって私はNetlifyのsnippet-injectionという機能を使ってNetlify側に設定しました。

Githubリポジトリに反映

ここまでで追加・修正したファイルをGithubリポジトリにcommit&pushしておきましょう。

ユーザーの招待

Accessing the CMSの手順に沿って行います。
手順を簡単に書きますと、IdentityタブからInvite usersを押して、自分のメールアドレスを入力して送信します。自分のメールアドレスに招待メールが届くので、Accept the inviteというリンクをクリックしてください。パスワードを設定したら登録完了です。(Githubなどのアカウントでログインする場合はパスワード不要です。私は最初に作ったときはうまくいったのですがこの手順を書きながらやっている今はなぜかGithubアカウントでのログインがうまくいかないのであきらめました…)
もしユーザーの招待で失敗してしまったら、一度Identityタブからユーザーを削除して、再度登録してみてください。

NetlifyCMSを動かしてみる

作ったサイトのURL/admin/
でCMS管理画面に入れます。管理画面の使い方については解説しませんが、とてもシンプルな作りになっているので説明がなくても使えると思います。

elm-uiの適用(任意)

https://package.elm-lang.org/packages/mdgriffith/elm-ui/latest/
elm-uiを使うと、CSSを頑張らなくてもページのレイアウトができます。Elmstaticの初期状態ではelm-cssが適用されていますので、お好みに合わせてライブラリを選定してください。以下の手順は、elm-uiを使う場合の準備内容や変更箇所です。

インストール

通常のelmパッケージのインストールと同じ手順でelm install mdgriffith/elm-uiしてください。

修正

Page.elmのlayout関数を思い切って修正してみてください。ページ全体のレイアウトが変わります。コミットログがあるので復元はいつでもできますし!私は以下のようなソースコードになりました。まだぐちゃぐちゃにいじっている途中です…。

Page.elmのlayout関数
_layouts/Page.elm
layout : String -> List (Html Never) -> List (Html Never)
layout title contentItems =
    [ Element.layout [ padding 20 ] <|
        column [ spacing 50 ] <|
            [ row []
                [ link []
                    { url = "/"
                    , label = image [ width <| px 48, height <| px 48 ] { src = "/img/logo.png", description = "ねぎぼうづぶろぐ" }
                    }
                , el [ Font.size 50, Font.family [ Font.monospace ] ] (text title)
                ]
            , row []
                [ column [ padding 10, spacing 10, alignTop, alignLeft ]
                    [ link [ Background.color (rgb255 255 240 240) ] { url = "/", label = text "トップ" }
                    , link [ Background.color (rgb255 255 240 240) ] { url = "posts", label = text "ぶろぐ" }
                    ]
                , column [ padding 10, alignTop, alignLeft, width fill ] <| List.map (\item -> html item) contentItems
                ]
            , row [] []
            ]
    ]

以下の2点は、記事Markdownに長いパラグラフを書いたときに文章が折り返されないことへの対応です。他に良いやり方があるのかもしれませんが、elm-uiとは別でCSSで設定しました。(折り返し対応は本当はword-breakoverflow-wrapで設定するものなのだと思うのですが、white-spaceしか効きませんでした…。

_layouts/Elmstatic.elm
, stylesheet "/styles.css"
_resources/styles.css
.markdown p {
    white-space: normal; 
}

Twitter対応

Twitter cardの設定

https://saruwakakun.com/html-css/reference/twitter-card#section4
こちらのサイトを見ながら以下の行を追加して設定しました。私の設定ではトップ階層へのリンクでしか画像が表示されないという不備があるので、改善の余地ありです。

_layouts/Elmstatic.elm

, node "meta" [ attribute "name" "twitter:card", attribute "content" "summary" ] []
, node "meta" [ attribute "name" "twitter:site", attribute "content" "@negiboudu" ] []
, node "meta" [ attribute "property" "og:url", attribute "content" "https://negiboudu-blog.netlify.app/" ] []
, node "meta" [ attribute "property" "og:title", attribute "content" "ねぎぼうづぶろぐ" ] []
, node "meta" [ attribute "property" "og:description", attribute "content" "twitterに書くとちょっと長くなりそうなこと" ] []
, node "meta" [ attribute "property" "og:image", attribute "content" "https://negiboudu-blog.netlify.app/img/logo.png" ] []

Tweet ボタンの埋め込み

https://help.twitter.com/ja/using-twitter/twitter-buttons
ここを見ながら作って、以下の行を追加しました。
_layouts/Elmstatic.elm
, script "//platform.twitter.com/widgets.js"
_layouts/Page.elm
, div [ class "link" ]
    [ a 
        [href "https://twitter.com/share?ref_src=twsrc%5Etfw", class "twitter-share-button"]
	[text "Tweet"]
    ]

つくったもの

まあひどい見た目ですがこれからですよ!

https://negiboudu-blog.netlify.app
https://github.com/negiboudu/elmstatic-blog

参考文献

https://qiita.com/y047aka/items/2f051035fd86a38145e2
https://izumisy.work/entry/2019/09/23/201040