Next.js 14のApp Routerで作ったブログをGitHub Pagesで公開する
Next.jsとGitHubのPages機能を使ってこのようなブログを公開できます。
https://ryukyuinteractive.github.io/next-template-blog/
リポジトリはこちらです。コピーして使えます。
https://github.com/RyukyuInteractive/next-template-blog
コマンドを使用してもリポジトリを作成することもできます。
$ npx create-next-app@latest --example https://github.com/RyukyuInteractive/next-template-blog
リポジトリのサイトはこのようなシンプルな見た目になっています。
見た目はVercelの公式のテンプレートを参考にしています。
https://vercel.com/templates/next.js/blog-starter-kit
マークダウン
マークダウンにはZennのライブラリを使用しています。
マークダウンをHTMLに変換するライブラリとCSSのライブラリが必要です。
npm i zenn-content-css zenn-markdown-html
CSSはlayoutなどで読み込みます。
import "zenn-content-css"
HTMLに変換するにはこのようにします。
import markdownToHtml from "zenn-markdown-html"
const html = markdownToHtml(post.body)
return (
<div
className="znc font-medium"
dangerouslySetInnerHTML={{ __html: html }}
/>
)
デプロイする
GitHubのPagesという機能を使ってサイトを公開します。
https://docs.github.com/ja/pages/getting-started-with-github-pages/about-github-pages
設定するとActionsが自動で作成されるのですが少し修正が必要になります。
修正内容
Node.jsのバージョンは20にしました。
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: "20"
App Routerでは next export は使用できないのでコメントアウトします。
# - name: Static HTML export with Next.js
# run: ${{ steps.detect-package-manager.outputs.runner }} next export
ファイルはこちらで確認できます。
https://github.com/RyukyuInteractive/next-template-blog/blob/main/.github/workflows/nextjs.yml
マークダウン
マークダウンの本文以外の情報はgray-matterというライブラリを使って取得しています。
import matter from "gray-matter"
const fileText = await readFile(fullPath, "utf-8")
const { data, content } = matter(fileText)
return {
title: data.title
}
マークダウンの情報は本文の上に記載します。
---
title: "Dynamic Routing and Static Generation"
date: "2020-03-16T05:35:07.322Z"
ogImage:
url: "/blog/dynamic-routing/cover.jpg"
---
型安全ではないですがある程度の複雑な情報でも取り出せます。
const { data, content } = matter(fileText)
return {
title: data.ogImage.url
}
コンポーネント
shadcn/uiというコンポーネントを使用しています。
https://ui.shadcn.com/docs/installation/next
これらを新しく追加するには以下のコマンドを実行します。
npx shadcn-ui@latest add
追加したコンポーネントは components/ui
に保存されます。
components
└── ui
├── avatar.tsx
├── badge.tsx
├── button.tsx
├── card.tsx
├── dropdown-menu.tsx
└── separator.tsx