
こんにちは!インプットした内容をまとめるためにブログを始めました。
Next.js、TypeScript、そしていくつかのライブラリを使って Markdown を活用したブログを作成しました。 Github Pages でホストしてカスタムドメインを割り当てています。
実際のソースコードはこちらです。 https://github.com/pochy/blog
このブログは執筆時点で Next.js 14.0.3 上に App Router を用いて構築しています。最初は Pages Router にしていましたが、学習も兼ねているので新しく登場した App Router に途中で切り替えました。
デザインに関しては、以下のライブラリを採用しています:
このプロジェクトでは、以下のライブラリを使用しています:
npx create-next-app@latest コマンドで Next.js のプロジェクトを作成します。
コマンド実行時に質問を聞かれますが、ここでは全部 Yes にしています。
$ npx create-next-app@latest blog
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like to use `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to customize the default import alias (@/*)? … No / Yes
Creating a new Next.js app in ~/blog.
Using npm.
Initializing project with template: app-tw
Installing dependencies:
- react
- react-dom
- next
Installing devDependencies:
- typescript
- @types/node
- @types/react
- @types/react-dom
- autoprefixer
- postcss
- tailwindcss
- eslint
- eslint-config-next
added 333 packages, and audited 334 packages in 13s
117 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Initialized a git repository.
Success! Created blog at ~/blog
作成されたディレクトリに移動して npm run dev コマンドで開発モードとして実行できます。
$ cd blog
$ npm run dev
> blog@0.1.0 dev
> next dev
▲ Next.js 14.0.3
- Local: http://localhost:3000
✓ Ready in 4s
ブラウザで http://localhost:3000 を開くと初期状態の画面が表示されます。

Markdown ファイルは _posts ディレクトリ以下に格納します。
$ mkdir -p _posts
$ touch _posts/test.md
---
title: Hello, World!
createdAt: 2023-11-30T00:00:45.855
updatedAt: 2023-11-35T13:13:18.250
---
# Hello, World!
サンプルテキスト
- リスト1
- リスト2
**太字**
~~取り消し線~~
必要なライブラリのインストール
$ npm install react-markdown gray-matter
added 88 packages, and audited 422 packages in 6s
184 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
_posts ディレクトリ以下から Markdown ファイルを読み込んで gray-matter を使用してパースします。
import fs from "fs";
import path from "path";
import matter from "gray-matter";
export type PostMeta = {
title: string;
createdAt: string;
updatedAt: string;
};
export type Post = PostMeta & {
id: string;
filePath: string;
content: string;
};
const postsDirectory = path.join(process.cwd(), "_posts");
export function getPostFilePaths(
dir = postsDirectory,
filePaths: string[] = [],
) {
const files = fs.readdirSync(dir);
files.forEach((file) => {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
getPostFilePaths(filePath, filePaths);
} else if (stat.isFile() && /\.md$/.test(filePath)) {
filePaths.push(filePath);
}
});
return filePaths;
}
export function getAllPosts() {
const postFilePaths = getPostFilePaths();
const allPostsData = postFilePaths.map((filePath) => {
const id = path.basename(filePath, ".md");
const fileContents = fs.readFileSync(filePath, "utf8");
const { data, content } = matter(fileContents);
const post: Post = {
id,
filePath: filePath.replace(/\.md$/, "").replace(postsDirectory + "/", ""),
content,
...(data as PostMeta),
};
return post;
});
return allPostsData;
}
初期状態で入ってるスタイルは使わないため削除し、先頭 3 行の Tailwind の部分のみ残します。
@tailwind base;
@tailwind components;
@tailwind utilities;
トップページに getAllPosts で取得した Markdown の内容を表示します。
表示には react-markdown を使用します。
import { getAllPosts } from "@/utils/posts";
import ReactMarkdown from "react-markdown";
export default function Home() {
const posts = getAllPosts();
return (
<div className="bg-gray-100">
<div className="container mt-10 pb-10 mx-auto px-0 sm:px-4 max-w-4xl">
{posts.map((post) => (
<div key={post.id} className="mx-auto p-4 bg-white rounded-lg">
<ReactMarkdown>{post.content}</ReactMarkdown>
</div>
))}
</div>
</div>
);
}
ブラウザで再度トップページを確認します。 Markdown の内容が表示されている事を確認します。

このままでは特にスタイルが適用されていないため、一旦 @tailwindcss/typography を使用します。
$ npm install @tailwindcss/typography
import type { Config } from "tailwindcss";
const config: Config = {
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
plugins: [require("@tailwindcss/typography")],
};
export default config;
- <ReactMarkdown>
+ <ReactMarkdown className="prose prose-sky mx-auto max-w-4xl">

スタイルが適用されました。
このブログの作成は Next.js と TypeScript と、Markdown に関するライブラリを使って技術的な知識を深める素晴らしい経験でした。デザインライブラリの Radix UI、Tailwind CSS、shadcn/ui の組み合わせは、とても心地よくこれからも積極的に採用していきたいと思います。
また、Markdown を活用することで、コンテンツ作成プロセスを大幅に効率化しました。