chibiham home page
Next.jsで作成しているこのホームページについて。
概要
ちびはむのプロフィール、ポートフォリオやブログ等を掲載し、エンジニアとしてのプレゼンスを上げるために開発・運用している。
アーキテクチャ

- Cloudflareでドメイン登録
- Next.jsアプリで運用したかった点、フロント/バックエンド分離するつもりがなかったため、Vercelを選択
- GitHubと連携するだけでブランチごとの自動デプロイが構成される
- グローバルCDN、自動スケーリング、モニタリング、DDoS対策、環境変数の管理など、運用機能も充実。Next.jsでのSSG, SSRに対応できる
- これらの機能を有しながらも、無料枠が充実しており、よほどのPVがない限り無料で運用可能
- かなり余裕がある

- Markdownによるコンテンツ管理
content/blog/、content/portfolio/配下にMarkdownファイルを配置し、Gitで管理- gray-matterでfrontmatter解析、next-mdx-remoteでレンダリング
- 以前はNotionをCMSとして使用していたが、シンプルなMarkdown管理に移行した(詳細は後述)
- Resend
- メール送信PaaS。コンタクトフォームのメール送信に使用。シンプルな使い心地で、無料枠も十分あり
技術スタック
- Next.js
- 静的なサイトとインタラクティブなサイトの両方を、SSGやSSRに対応することでユーザー体験とコストパフォーマンスよく提供できるため
- フロントエンドとバックエンドを統合させつつ、Reactを使用したコンポーネントベースの開発が可能なため
- 複雑なバックエンド処理は存在しないため、SSRとServer Actionsを使用し、簡素な作りに留めている
- Tailwind CSS
- SSGに対応させたかったため、また、Reactのコンポーネント開発においてデメリットの少ないユーティリティファーストなTailwindを選択
デザイン
開発初期のデザイン検討として、Figmaを使用。個人開発のためオンコードで調整した方が早い側面があるため細部には時間をかけていない。
- Gridデザインを適用した画面全体のレイアウトの調整(約2h)
- 背景、ロゴ、アイコン画像の作成(約2h)

- アイキャッチ画像はnijijourney(Midjourney)で作成
- ちびはむのアイコンは、手書きイラストをnijijourneyによるi2iで作成後、Photoshopで細部調整
![]()
機能
Grid Designによるレスポンシブデザイン
Tailwind CSSのGridを使用し、レスポンシブデザインに対応。
ダークモード対応
Tailwind CSSのダークモードのテーマを設定、各コンポーネントでダークモード使用時のCSSを調整し対応。ブラウザの設定によってダークモードが適用される。
多言語対応
i18next、next-i18n-routerを使用して多言語化対応。詳細は記事参照。
ブログやポートフォリオの記事コンテンツ自体は、ロケールごとにMarkdownファイルを用意することで多言語対応している。
SEO対策
検索エンジン最適化を多角的に実装している。
- JSON-LD構造化データ: 各記事ページにArticleSchemaを埋め込み、Google Rich Resultsに対応
- Open Graph / Twitter Cards: 記事ごとにタイトル・説明・カバー画像を動的に生成し、SNSシェア時の表示を最適化
- 動的サイトマップ:
sitemap.tsでブログ・ポートフォリオの全記事を含むXMLサイトマップを自動生成 - canonical URL / hreflang: 各ページのcanonical URLとロケール別の代替URLを設定し、多言語サイトのSEOに対応
コンタクトフォーム
Next.jsのServer Actionsを使用したフォーム送信を実装。
- Zodによるバリデーション。zod-i18n-mapを使用し、エラーメッセージもブラウザの言語設定に応じて日英で表示される
- Resend + react-emailでリッチテキストメールを送信。送信者と管理者の双方にメールが届く
- Reactコンポーネントでメールテンプレートを構築しているため、フロントエンドとほぼ同様の実装で多言語にも対応

MDXカスタムコンポーネント
Markdownレンダリングにnext-mdx-remoteを使用し、以下のカスタムコンポーネントを実装している。
- CodeBlock: rehype-prism-plusによるシンタックスハイライト
- MermaidBlock: Mermaid図のクライアントサイドレンダリング。ダークモード切替時に自動で再レンダリングされる
- Callout: 情報・警告などのコールアウトボックス
- テーブル・引用・リスト等: 全Markdown要素にダークモード対応のスタイリングを適用
Atomic Designによるコンポーネント設計
コンポーネントをAtoms / Molecules / Organismsの3層で整理し、再利用性と保守性を確保している。
コンテンツ管理:Notion CMSからMarkdownへの移行
当初はNotionをCMSとして活用していた。Notion APIで取得した各Blockに対応するコンポーネントを一つ一つ用意し、Claude 3.7 Sonnetを活用してAPIの型に合わせたコンポーネントを生成・調整することで、ほぼ全てのブロックを約3hで実装した。
しかし、運用を続ける中でNotionをCMSとして使い続ける必要性が薄れ、シンプルなMarkdownファイルによる管理に移行した。
移行の背景:
- 個人のナレッジ管理をNotionからObsidianに移行したことが最大の要因。記事の執筆・管理もObsidian vault内で完結させたかった
- Obsidianで書いたMarkdownをそのままホームページのコンテンツとして使えるため、執筆からデプロイまでのフローがシンプルになる
- Notion APIへの依存により、ビルド時の外部通信やキャッシュ管理が必要だった
- ブロックごとのコンポーネント対応のメンテナンスコストがあった
現在の構成:
content/blog/{locale}/{slug}.mdにMarkdownファイルを配置- YAML frontmatter(title, description, cover, date, tags等)でメタデータを管理
- gray-matterでfrontmatter解析、next-mdx-remoteでMDXレンダリング
- Mermaid図やKaTeX数式、コードブロックのシンタックスハイライトにも対応
- ロケールごとのサブディレクトリ(
ja/,en/)で多言語コンテンツを管理 - Next.jsの
generateStaticParams()によるビルド時静的生成
