Notion を Hugo のヘッドレスCMSとして利用する方法 [Notion Hugo Exporter] Hugo のサイトで Notion をヘッドレスCMSとして利用するためのソフトウェア
By fand.jp |
Saturday, December 03, 2022
English version here
参照サイト GitHub - dobassy/notion-hugo-exporter: Use "Notion" as a Headless CMS to generate a content file for Hugo. Use "Notion" as a Headless CMS to generate a content file for Hugo. - GitHub - dobassy/notion-hugo-exporter: Use "Notion" as a Headless CMS …
By github.com
Use “Notion ” as a Headless CMS to generate a content file for Hugo .
このソフトウェアは、Webサイトのコンテンツ管理を Notion で実現することを目的に作成されました。Notion 上で作成したページを Hugo のコンテンツ(=Markdownファイル)として出力するように設計しています。Markdownファイルとして出力した後の挙動は Hugo の仕様に準拠します。
この役割の分離により、仮にコンテンツ管理を Notion からその他のサービスへ移行したいと思った時、データベースのエクスポートなどの面倒な処理が発生しないので容易に乗り換えることが可能となります。
バージョン 2022/12現在、バージョン 0.x の状態です。破壊的な仕様変更には最大限考慮しますが、破壊的変更が発生する可能性もあります。
提供機能 Notion 上の指定するデータベースに作成されているページ単位でMarkdownファイルを生成します Notion API へのリクエストを軽減するためにローカルキャッシュを持っています Notion ページに含まれる画像が Amazon S3 に保存されている場合、有効期限付きのURLであり、このまま公開すると不都合があるため処理を停止します(この挙動を無効化することもできます) Notion ページに含まれる画像をダウンロードします。ダウンロードした画像は static
ディレクトリに保存して公開できるほか、独自に作成した Javascript の callback 処理をフックすることができます ダウンロードした画像は、 .webp
フォーマットに変換することができます 記事の絶対パス (Url
) あるいは相対パス( Slug
) に記入した文字列は kebab-case で変換するため、URLの作成が少し楽になりますUrl
や Slug
は Hugo の仕様による設定項目です その他いくつかの設定は Configuration を参照してください Permission (Notion API) Notion Hugo Exporter は Notion ページへの書き込みを行いません。よって、Read 権限の Token のみで動作します。
書き込み権限があればデータベースの初回セットアップが楽になりますが、裏返すとその時にしか主な活躍場面がありません。余計な書き込み権限を有することによる、不本意なデータ破壊を回避することを優先しています。
実行の前提条件 Node を利用します (v18で開発していますが、一般的なライブラリしか利用していないので v12 くらいまでは動作すると思いますが未確認です) npm へは公開していません(まだ) Docker Image を提供しています Quickstart 1. トークンの設定 export NOTION_TOKEN=
export NOTION_BLOG_DATABASE_ID=
2. Notion データベースプロパティの作成 プロパティは、以下の図で表示対象としている (Shown in table)プロパティがあれば動作します。その他、任意で非表示(Hidden in table)部分にあるプロパティのように Hugo のコンテンツで利用する値としてカスタマイズしたり、自身の管理メモとして任意の数のプロパティを追加できます。(なお、ここで説明した表示・非表示には意味はありません。図の説明用でグルーピングしているだけです)
必要プロパティの詳細は後述していますので参照してください。
3. コマンドの実行 ここでは Docker で動かす場合とします。
docker run -it --rm \
-e NOTION_TOKEN= $NOTION_TOKEN \
-e NOTION_BLOG_DATABASE_ID= $NOTION_BLOG_DATABASE_ID \
-v $( pwd) /notion-hugo.config.js:/work/notion-hugo.config.js \
-v $( pwd) /content/:/work/content/ \
-v $( pwd) /static/:/work/static/ \
-v $( pwd) /.notion-hugo-cache/:/work/.notion-hugo-cache/ \
dobassy/notion-hugo-exporter:latest
Mount four files or directories.
notion-hugo.config.js
: いろいろな設定ファイル(後述)content/
: Markdown コンテンツを出力する先static/
: 画像をダウンロードする場合は static ディレクトリへ配置します.notion-hugo-cache/
: Notion Hugo Exporter の管理用キャッシュデータです。仮に削除しても、全てのファイルを Notion API から取得し直すだけです。ローカル環境で動かしたい場合は以下のようにビルドしてください。
git clone ...
npm install
npm link
Configuration notion-hugo.config.js
に設定可能なパラメタは以下の通りです。サンプルファイルがあるので参照してください。
module .exports = {
directory : string ,
concurrency : number ,
authorName : string ,
s3ImageUrlWarningEnabled : boolean ,
s3ImageUrlReplaceEnabled : boolean ,
s3ImageConvertToWebpEnalbed : boolean ,
useOriginalConverter : boolean ,
saveAwsImageDirectory : null | string ,
downloadImageCallback : null | func (),
customTransformerCallback : null | func (),
};
directory
: (必須) コンテンツファイルを書き出すディレクトリconcurrency
: 同時実行数。増やしすぎないほうがいいかもしれない。Defaults to 5
.authorName
: 記事の author を強制で固定します。一人でサイト運営している時には都合がいいでしょうs3ImageUrlWarningEnabled
: Defaults to true
. Amazon S3の画像が含まれている場合に警告を出してプログラムの動作を停止しますs3ImageUrlReplaceEnabled
(Experimental): Defaults to false
. Notion コンテンツに S3 URL が含まれている場合は、ダウンロード後にそれらをローカル パスに置き換えます。 この機能は、画像管理にかかる時間と労力の削減を目的としています。s3ImageConvertToWebpEnalbed
: Defaults to false
. ダウンロードした画像を .webp
へ変換しますuseOriginalConverter
: Defaults to false
. Markdown へ変換した後の行間の調整をしています。利用している Markdown 変換ライブラリの都合ですが、癖があって好みではなかったので微調整しました。その挙動を On/Offできます。お好みで。utcOffset
: Defaults to null
as “Z
”. Notion で設定した時刻が UTC だった場合に調整するものです。日本なら “+09:00
”saveAwsImageDirectory
: Defaults to null
. S3画像をダウンロードするディレクトリdownloadImageCallback
: Defaults to null
. ダウンロードした画像に対して任意のコールバック処理を加えることができます。例えば、ダウンロード後に WordPress API を利用して画像をアップロードするサンプルを notion-hugo.config.02callback-sample.js
に記載しています。fetchInterval
: Server Mode で動かすときのインターバル。60秒より短くしても意味がないcustomTransformerCallback
: Notion API のブロックに対する独自処理を追加。オリジナルライブラリの説明を参照 See also https://github.com/souvikinator/notion-to-md#custom-transformers プロパティ Notion データベースには以下のプロパティを設定してください。
Property Name Type Required Default value isPublished Boolean ✅ Category Select ✅ Tags multi_select ✅ PublishedAt date ✅ UpdatedAt date ✅ Url Text ✅ (Either Url or Slug) Slug Text ✅ (Either Url or Slug) Description Text ✅ Image Image (external url) ✅ Section Select ✅ Author Text or Select “Writer” isDraft Boolean false filepath Text
これらプロパティは手動で作成してください(前述の通り) filepath
property: ディレクトリとファイル名を記入することで、Markdownの書き出す場所を強制することができます。例えば blog/category/_index.md
のような特殊なファイルを作成する時に都合が良いです。その他任意のプロパティ Property Name Type linkTitle Text weight Number
これらのパラメタは Docsy テーマを利用するときに都合がいいです。(Docsyで利用します)
ユーザーが定義する任意のプロパティ Frontmatter に任意のプロパティを追加できます。
例えば、技術系ドキュメントでは「この記事は古いです」というアラートを出すことがありますが、記事によってその挙動を変えたい時があるでしょう。その場合、 ToC
フラグ(以下の例)がある記事にのみ挙動を適用する、といった柔軟性が向上します。
v0.6時点、 text
型と boolean
型にのみ対応しています。
// array[0]: property name in Notion
// array[1]: Types identified when exporting to Frontmatter (Markdown)
customProperties : [
["ToC" , "boolean" ],
["AdditionalDescription" , "text" ],
],
実例 オリジナルページ(Notion)
FrontMatter Notion Hugo Exporter を実行して生成された Markdown ファイル
---
sys :
pageId : "01234567-0123-4567-8901-dummy1dummy2"
createdTime : "2022-02-01T15:54:00.000Z"
lastEditedTime : "2022-02-01T15:56:00.000Z"
title : "Example page"
date : "2022-02-01T00:00:00.000+09:00"
description : "Description here"
tags :
- "API"
- "Development"
categories :
- "Notion"
toc : true
author : "Writer"
legacy_alert : false
draft : false
url : "/hugo-notion-example-page"
section : "technologies"
---
# Hugo Notion
hello, world
Body 本文の生成は、基本的には外部ライブラリ “notion-to-md” に依存しています。
souvikinator/notion-to-md: Convert notion pages, block and list of blocks to markdown (supports nesting)
キャッシュ Notion の pageId を主キーとして、Notion のページの最終更新日をキャッシュします。
Notion API へのリクエスト数を最小限に抑えるために、取得したページの日時をキャッシュします。 ディレクトリ .notion-hugo-cache/
を削除すれば初期化されます(コンテンツ本体には影響はありません)
例えば以下のように、特定のURLに対して独自の Shortcode を適用することが可能です。CustomTransformer を使うには、 Notion APIのブロック構造を理解する力が必要です。
const customTransformerCallback = (n2m ) => {
n2m .setCustomTransformer ("bookmark" , async (block ) => {
const { bookmark } = block ;
if (! bookmark ? .url ) return "" ;
return `\{\{<blogcard " ${ bookmark .url } ">\}\}` ;
});
};
Original output:
[bookmark ](https://github.com/ )
After transform output:
{{<blogcard "https://github.com/">}}
Markdownファイルの行間の調整 notion-to-md version 2.5.1 での仕様変更により、段落に複数の改行が挿入されました。 好みの問題ですが、従来の仕様で段落の改行数を扱えるようにカスタマイズしました。 ライブラリの将来の更新により、この機能が廃止される可能性があります。
元のライブラリ仕様を使用する場合は、設定を true に設定することで動作を変更できます。
useOriginalConverter: true
例(検証コンテンツ)
左:オリジナル動作ではない 場合
右:オリジナル動作の場合(行間が多い)
なおMarkdownファイル上でこの行間があっても、HTMLに変更する上では適切な paragraph
の単位に変換されるので結果的には問題ないのですが、好みによるものです。
Watch mode (Server mode) Notion ページのエクスポートには時間がかかるため、コマンドを 1 つずつ実行するのは面倒です。 --server
オプションを使用して監視モードに入ることができます。
このモードでは、Notion の更新が定期的にチェックされ、ページが生成されます。 Hugo の hugo server
コマンドと併用することで、リアルタイムプレビューのような使い方ができます。ただし、Notion API経由での変更検知の最小単位が「分」だったので、同じ分数で何回変更しても変化を検知できません。将来的なNotion APIの仕様変更により改善されることを期待しています。
Foreman や Hivemind などのプロセス マネージャーを利用すると便利です。 以下は、Procfile の構成方法の例です。
notion: notion-hugo -S
hugo: hugo server --ignoreCache --buildFuture