【Notionブログ化】nextjs-notion-starter-kitの構築
【Notionブログ化】nextjs-notion-starter-kitの構築

【Notionブログ化】nextjs-notion-starter-kitの構築

Created
Nov 1, 2022 04:07 AM
Updated
Last updated December 10, 2022
Tags
Next.js
Vercel
Notion
Description
entsuka-logというNotionと連携したWEBサイトを作成しました。元はOSSでNotionを編集すればそのまま反映されて公開できます。いままでのブログ記事作成と比べてブログ用の画像を選ぶ手間がほとんど無いのと、Notionの気持ちの良い操作体験のまま作成できるのが良いです!その作り方を残しておきます📓

最初にまとめ🫖

  • site.config.ts を設定🧑‍💻
  • npm run deploy を実行🧑‍💻
Notionの設定方法、リポジトリ内の設定、運営する上での注意事項なども残していきます。
 
例1) Google Analyticsの導入はどうするか?
例2) 公開リポジトリみたいにサイト上で表示するには?
などなど
 
読者は、エンジニア経験がちょっとでもある方を想定しています。
プログラミングを全く触ったことが無い方は作り上げるの大変かもです。すいません🙇‍♂️
 

このブログの何が良いか?💘

  • Notion上で編集すればそのまま反映されて公開できます。
    • 厳密には異なったり実現できないNotionのデータベースがありますが、ほぼほぼ同じUIでブログ公開できるので、プレビューして確認する手間が減る。
  • 従来のブログ記事作成と比べてブログ用の画像を選ぶ手間がほとんど無い。
    • Vercelのライブラリで自動生成してくれる。
  • Notionの気持ちの良い操作体験のまま作成できる。
    • WordPressのブロック作成をポチポチせずにNotionのショートカットキー / からゴリゴリ簡単に作成できちゃう。
 
つまり、最&高。
 
へ?Notionページをそのまま公開すれば良くない?
とも思いましたが、
  • Analyticsを入れ込むことができて自分のモチベーションになる。
  • SNSシェアがOGP生成してくれるので楽。
  • 自分でコードいじって拡張したり試したりできる余地があるのでエンジニアとしても楽しめる。
といった感じでやってみました。
 

公開リポジトリをクローン🧑‍💻

まずはリポジトリを自分の環境に持ってきて、パッケージ関連をインストールします。載せるのもあれですが一応。
$ cd ~ $ git clone git@github.com:transitive-bullshit/nextjs-notion-starter-kit.git $ cd nextjs-notion-starter-kit $ npm install
 
ローカルで起動はするには
$ npm ruv dev
このあたりは、 readme.md にも書いてあります。
 

site.config.tsを設定🧑‍💻

site.config.ts を自身のNotion環境やお好みに合わせて設定する必要があります。
私が特に設定していない箇所は割愛しています。
import { siteConfig } from './lib/site-config' export default siteConfig({ // ブログ化するトップページのidを埋め込みます。 // idはブラウザからnotionへログインしてページを表示した時のパスです。 rootNotionPageId: 'entsuka-log-9b29494b22d44554a78cf409bf15f486', // ここでの設定はブログにデフォルトで表示されるものだったりです。 // 実際に公開する時のdomainは自分で取得する必要があります。 name: 'entsuka-log', domain: 'entsuka-log.site', author: 'entsuka', // トップページで表示するdescriptionタグの内容です。 description: '地方製造業⚙️ → 都内ITベンチャー → 地方フルリモートWEBエンジニア | 30代からベンチャーへ転職 | TypeScriptがメイン | 使い勝手の良いエンジニア🧑‍💻 | 複数の企業さんとお仕事してる | 毎日の自転車で痩せるのが目標🚲', // SNSアイコンを記述の内容で表示させます。 twitter: 'entsuka', // ページにアイコン設定しない時のデフォルトアイコンだったり、デフォルトカバー画像を設定します。 defaultPageIcon: "🎧", defaultPageCover: 'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?ixlib=rb-4.0.3&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=2400', defaultPageCoverPosition: 0.5, // ナビを表示させることができます。idはブラウザで自身のNotionページへアクセスしてURIから確認してください。 navigationStyle: 'custom', navigationLinks: [ { title: 'about', pageId: 'about-bfadbf93121846da860b80028fa3a34f' }, { title: 'idea', pageId: 'idea-2429a96e63474e7cb4fba8ee9651cc05' } ] })
 

npm run deployを実行🧑‍💻

コマンドでVercel上にデプロイさせます。
今回Vercelはじめまして、でしたがアカウント作成もスムーズで滞りなくできて良かったです。
 
次回以降は、なにかリポジトリに変更を加えて push するタイミングでVercel上でビルドが自動で走り変更が反映された状態でデプロイされます。便利!
 

その他の設定や運用や注意事項などなど

いざ画面を表示してみると、ここちょっとテコ入れしたいとかでてきました。
  • Githubリポジトリシェアボタンを非表示にしたい
  • Google Analyticsいれてみたい
  • もし商用利用したい時とかどうしよう
  • Twitterでのリンクシェア時のOGP画像がうまく表示されない
  • リポジトリ内にあるようなブログの表示ができない
 

Githubリポジトリシェアボタンを非表示にしたい

これは、シンプルで /components/GitHubShareButton.tsx がありまして、これを利用しているページで削除してしまえばOKです。
 

Google Analyticsいれてみたい

以下のような内容でファイル作成。
// /components/GoogleAnalyticsTag.tsx import * as React from 'react' import Script from 'next/script'; export const GA_ID = "hogehoge"; const GoogleAnalyticsTag: React.FC = () => { return ( <> <Script defer src={`https://www.googletagmanager.com/gtag/js?id=${GA_ID}`} strategy="afterInteractive" /> <Script defer strategy="afterInteractive"> { ` window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', '${GA_ID}'); ` } </Script> </> ) } export default GoogleAnalyticsTag;
 
作成したものを追加。
// /components/PageHead.tsx import GoogleAnalyticsTag from './GoogleAnalyticsTag' export const PageHead: React.FC< types.PageProps & { title?: string description?: string image?: string url?: string } > = ({ site, title, description, pageId, image, url }) => { // ~~~省略~~~ // return ( <> <GoogleAnalyticsTag /> {/* 追加 */} {/* 以下省略 */} </> )
 
Google Analyticsの設定は以下のリンクが参考になりました。
Next.jsでGoogle Analyticsを使えるようにする - パンダのプログラミングブログ
Next.js とはVercelが作成しているReactのフレームワークです。**面倒な設定を書かなくてもすぐに使えるZero Configを標榜しており、実際にwebpackやTypeScriptと一緒にReactを書く際にも特別な準備は不要です。SSRにも対応しており、Reactで開発するならNext.jsかFacebook製のCreate React Appを使うのがスタンダードになってます。 私は実務でNext.jsを使っており、このフレームワークはとても便利だと思っています。私はNext.jsの大ファンなので、Reactでの開発時にNext.jsを使う現場が増えるといいなと思って記事を書いています。 関連記事: Next.js + esa.io + VercelでJAMStackな爆速ブログを構築する **この記事では、Next.jsでReactアプリケーションを作成する時に、Google Analytics(以下、GA)の設定をする方法をご紹介します。**一通り設定した後、TypeScript化していきます。 基本的にはNext.jsの Example を参考にしています。ただ、実務で使うとこれだけでは足りないところがあるので、記事内では実務への橋渡しとなるような内容を盛り込んでいます。 なお、Google Analyticsのアカウント取得方法やスニペットの取得方法は記載していません。 まず、ルートディレクトリに.envファイルを作成し、GAのIDを.envに記述します。 NEXT_PUBLIC_GOOGLE_ANALYTICS_ID=UA-SOME_ANALYTICS_ID-1 Next.jsでは、.envに記述した環境変数を process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS_ID で取得できます。この値はビルド時に注入されます。これが最初の設定です。 NEXT_PUBLIC_という接頭辞をつけると、 ブラウザにも露出する値になります。 次に、GAイベントを発火させる関数を作成します。関数はsrc/lib/gtag.jsというファイルに記述していきます。 このファイルではgtagというGAのメソッドをラップする関数を作ります。 pageviewという関数でページビューを送信するには、 configコマンドを使用します。引数でパスを受け取り、 page_path でURLのパスを送信します。 event という関数でGAイベントを送信する関数を記述します。例えば、DOMのクリックイベントやSubmitのイベントなどを取得する時に使います。 なお、GAに関する詳しい内容はGoogleの公式ドキュメントをご覧ください。 _app.jsは全てのページで共通のHTMLを書くコンポーネントです。 この_app.jsにGA用のscriptタグを記述します。 これで Google Analytics の JS を読み込むことができました。 Next.js の v11 から、 Script コンポーネントが導入されました。 このコンポーネントを用いると、外部の JS を読み込むタイミングを簡単に制御できます。 ここでは、Script タグを使って Google Analytics の JS をサイトの実行に必要なスクリプトを読み込んでページがインタラクティブになった後に読み込むことで、ページが操作可能になるまでの時間を短縮する書き方を紹介します。 その恩恵を端的に書くと、Lighthouse でのスコアが上昇し、SEO に好影響を与えます。 src/components/GoogleAnalytics.js GoogleAnalytics コンポーネントはこれだけです。先程_app.js に書いたものを切り出しただけです。 あとは_app.js でこのコンポーネントを呼び出すだけです。 これで Google Analytics の読み込みタイミングを遅らせることができました。 Next.js製のサイトはSPAであるため、ページを遷移するときにJavaScriptでURLを書き換えます。その際、Google Analyticsはアクセスした最初のページしかページビュー測定のイベントを送信しません。つまり、ユーザーがサイト内を回遊したときの各ページのPVを測定できないのです。 この問題は、Next.jsのRouterを使えば解決できます。 RouterのURL書き換えが完了した時に発火するrouteChangeCompleteイベントのコールバックとしてpageview関数を設定します。 これを pages/_app.js ...
Next.jsでGoogle Analyticsを使えるようにする - パンダのプログラミングブログ
 
まだよくわかっていないこととして、新しくGoogle AnalyticsでGA4というものがでていますが、イベント取得時に重複して送信してしまうかもしれないということです。
ひとまずは上記の記載で様子をみて、挙動がおかしければテコ入れしてみます。
→確認してみた感じ問題なさそうでした🙆‍♂️
 

もし商用利用したい時とかどうしよう

Vercelは無料で利用できますが、商用利用(広告貼り付け・アフィリエイトリンクなどなど)するには規約上有料化する必要があります。$20。
Vercel の料金形態と内容についてまとめた - 2020冬
この記事は #EveOneZenn (Everyday One Zenn) vol.14 です。 Next.js などを手掛ける Vercel Inc.(旧 Zeit )が運営しているサービス、Vercel(旧 Zeit Now)の料金形態とその内容についてまとめます。 なお、掲載内容は 2020/12/08 時点のものです。 (過去に別所で公開していた記事の加筆版です) Note: 2020/12/08 19:51 - Hobby プランは個人的かつ非営利目的な目的でのみ利用できる旨を追記 Note: 2021/02/06 - 禁止されている用途について追記 Note: 2021/02/11 - Hobby プランにおける広告を掲載した、個人ブログでの利用について追記 Note: 2022/02/26 - Hobby プランにおける広告掲載の利用不可について追記 前回: Vercel は静的サイトとサーバレス機能のホスティングを提供するクラウドプラットフォームです。 JAMStack な Web サイトやサービスをホストしてアプリケーションを簡単にデプロイできます。 スケーリングやサーバーの監視は Vercel が行うため、開発者は Vercel へデプロイするだけでアプリケーションを公開・運用できます。 Vercel へデプロイできるアプリケーションのサンプルは GitHub のリポジトリに各種フレームワーク・ライブラリを使用した例が公開されています。 Vercel の料金プランには Hobby・Pro・Enterprise の 3 種類があります。 これらのプランは 2020/04/09 のアナウンスで発表されました。 各プランに含まれる機能は次のページで説明されています。 無料(従量課金なし) ※個人的かつ非営利な目的でのみの利用に限定 商用利用の定義については Fair Use Policy の Commercial Usage をご確認ください。 2021/02/08 より「広告を掲載していても、パーソナルな用途であれば問題ない」旨の記載をしておりましたが、規約上誤りであったため修正します。 誤情報を記載してしまい申し訳ございません。 Vercel の利用規約の商用利用に該当する用途について以下の記載があります。 The inclusion of advertisements, including but not limited to online advertising platforms like Google AdSense.
Vercel の料金形態と内容についてまとめた - 2020冬
 
Next.jsをサクッと低料金もしくは無料で利用するには、以下の技術選定が思いつきます。
  • Vercel
  • AWS Amplify
  • Firebase Hosting
  • Netlify
などなど。色々制限だったりトレードオフがあります。
Next.jsのホスティング先比較
Nextと同じ開発元のため相性良い SSR が標準でできる 個人無料 商用利用するには有料版のみ Pro版 約2400円/月 business版 従量次第 商用にするとコストが高いからスケールするときつい zennブログ元々Vercelだったが、のちにGoogle App Engineに移行した。 静的ページでmiddlewareを動かせる ※Vercel以外も一部制限あるができる 200Gまで無料  無料で商用利用可 Pro版 約2300円/月 business版 約12000円 応答速度がVercelの4倍-5倍ぐらいある (日本にCDNがないことが原因のため、CDNを別で用意することで解決可能?) ファイルダウンロードが遅い (TCPのコネクション1つだけ使用されるかららしい) ビルド時500エラーが起きやすい(ライブラリの相性か何かでVercelでは起きないエラーがたまに起きる可能性あり?) 10GB まで無料 SSRのパフォーマンスに問題あり 初回アクセスが遅い (Cloud Functionsの起動時間が必要) リージョン変えると動かない メモリ、ファイルサイズ等制限が多い ISRとSSRができなさそう? URLが変えられない(リポジトリ名に紐づく) スタンダード環境では無償利用枠がある が、実際は無料範囲内で納めるのは難しそう 利用額上限設定可能 フレキシブル環境は青天井のため注意が必要 スタンダード環境ではリクエストタイムアウトが60秒の制限がある deployが簡単 yml作るだけ preview がない 等機能が少ないらしい SSR対応可能 ISRは不可 AWS側がサポートするNextバージョンしか使えない AWSログイン必須で他のサービスに比べて操作がややこしい amplifyがサポートしていないことをしたい場合に難しくなる
Next.jsのホスティング先比較
 
また、色々調べているとホスティング先によってはSSR周りをサポートしていなかったり、していたり。ISRをサポートしていたり、していなかったり。
 
以下、自分調べ(○: Good, △: 条件あり, ✗: NG, -: 未調査)
Vercel
Amplify
Firebase
Netlify
料金
○(無料)
○(激安多分〜1000円)
○(無料)
○(無料)
商用利用
△(プラン変更$20)
-
技術サポート
△(ISRが未)
△(SSRパフォーマンスが…)
△(応答速度…)
導入しやすさ
△ ~ ○
順位
1
1 ~ 2
4
2
ということで、Amplifyをちょいと試してみたのと実際にコード読んで後から気づいたのもありますが、
  • SSR周りのビルドで見事にコケてしまう。
  • SNSでシェアで生成するOGPがVercel依存している。
ということで、結果Vercelでいくことにしました。
 
このあたりを解決できれば、Amplifyで低コストでかつ商用利用とかもできると思います。わたしの場合、この解決にかける時間的なコストを考えたら見合わなかったので、Vercelでいくことにしました。商用利用できたらいいけど、する予定もなかったので。
 

Twitterでのリンクシェア時のOGP画像がうまく表示されない

コードを良く追っていくと、OGP生成する時のアイコン画像が必須になっています。
必須というか、著者画像をアップロードする前提のコードになっています。
Zennとかで利用している絵文字を利用すると、srcをあてがうのに文字列が入ることになるので、Errorを吐いてOGP生成がうまくいかないようです。
コードをちょちょいといじれば一応どちらも対応できるようにテコ入れできます。
 

リポジトリ内にあるようなブログの表示ができない

これは、Notion側の設定で対応できるようになります。
まず、ギャラリービューとテーブルビューを組み合わせたテーブルを作成する必要があります。
ギャラリービューではサイトでのブログ表示を設定して、テーブルビューではブログで表示する項目を設定できます。
例えば以下の様なことができます。
  • ギャラリービューでカバー画像を表示したい
  • ギャラリービューでDescriptionやタグを表示したい
  • 特定の記事を非表示にしたい

ギャラリービューでカバー画像を表示したい

以下画像のように、ギャラリービューの3点リーダーから、カードプレビューというものを選択します。
カードプレビューからページカバー画像を選択することで、カバー画像を表示することができます。
notion image

ギャラリービューでDescriptionやタグを表示したい

画像のようにプロパティから、ギャラリーで表示する項目をドラッグ&ドロップして調整することで、表示させることができます。
このプロパティは、ギャラリービューと一緒に作成したテーブルビューに追加するもので、プロパティはテーブルビューで管理する形になります。
notion image

特定の記事を非表示にしたい

これはプロパティが表示された画像にもある通り、Publicというプロパティをテーブルビューに準備しておいて、それがチェック入っているものだけ表示するという方法でできます。
ギャラリービューのフィルターから、Publicにチェックありという設定にすれば、Publicチェックありなしで表示/非表示設定ができます。
notion image
ざっとこんな感じです。
 

追記

いくつか課題を確認したので残しておきます。
  • タイトルを変更するとURLも変わってしまう。
  • タグを削除すると残って表示されてしまう。
    • タグはあくまで外すまで
  • URLがタイトルを参照しているけど、日本語を参照していてクソダサい。
    • これはテーブルビューのプロパティにSlug(テキスト)を追加して、そこに記入すれば上書きできるようになります。(ちゃんとREAD.ME見てなかった…)
 
そこまで重要度を高く感じていないので、気が向いたら直してみます。
とりあえず、リリースしようぜ精神でいきます。