🥂

1997〜2018年のブログをReactで再構成し、記録として独自ドメインで保存する

に公開

はじめに

1997年から2018年まで書き続けていたホームページを、記録として保存することを目的としました。2004年以降は、Perl製の軽量CMS「ブロッサム(Blosxom)」でブログを管理していましたが、これを外してReactで構成し直すことにしました。

写真を一覧に含めたほうが直感的に見やすいため、サムネイル画像と日付を並べて表示し、クリックで各記事へ遷移できるUIに再設計しました。

記事ファイルはすべてSHIFT_JISで保存していたため、UTF-8への一括変換する必要がありました。

コンセプト

静的なHTMLをやめ、記事情報をJSONデータに変換し、Reactと組み合わせることで一覧表示をスクリプトで自動化しました。内容はそのままに、構造的に整理された形で記録として残すことを重視しました。

見やすいデザインと、年別に分類されたナビゲーションで、過去記事に直感的にアクセスできるUIを実現しています。個人的な記録を、技術的にも扱いやすい形を目指しました。

GitHubリポジトリ

https://github.com/kkoisland/kkoisland-react-cms

git clone git@github.com:kkoisland/kkoisland-react-cms.git
cd kkoisland-react-cms
npm install
npm start
# アクセス: http://localhost:3000/

公開デモ

https://past.kkoisland.com/

  • GitHub Pages(gh-pagesブランチ)を使用
  • gh-pages ブランチを独自ドメイン(past.kkoisland.com)にマッピングして公開

技術スタック

  • React (Create React App + TypeScript)
  • React Router(ページ遷移)
  • SCSS(コンポーネント単位のスタイル管理)
  • Font Awesome(ソーシャルアイコン)
  • Perl(SHIFT_JISからUTF-8変換、HTML抽出)
  • JSON(記事データ管理)

開発環境のセットアップ

npx create-react-app kkoisland-react-cms --template typescript

# Lint / Format
npm install --save-dev eslint prettier

# Routing
npm install react-router-dom @types/react-router-dom

# Styling
npm install sass

# Font Awesome
npm install @fortawesome/react-fontawesome \
            @fortawesome/fontawesome-svg-core \
            @fortawesome/free-brands-svg-icons

GitHub Pagesでの公開

  • ビルド成果物(build/)を gh-pages ブランチにデプロイ
  • 独自ドメイン(past.kkoisland.com)は CNAME ファイルで指定
    この CNAME ファイルを gh-pages ブランチに含めることで、GitHub Pages の公開先と独自ドメインを結びつける仕組みです。

デプロイ方法

npm run build  # build/生成
npm run deploy # gh-pagesにpush

実装した主な機能

  • 年別リスト表示(YearList):クリックで詳細表示へ
  • ダークモード切替対応
  • ホバーアニメーション(画像、リンク)
  • グローバルスタイル(SCSS)とユーティリティスタイル整備
  • 画像の有無に応じたフォールバック表示
  • 記事メタデータのJSON分離と読み込み
  • Perlスクリプトによる文字コード変換&記事抽出

scripts/ ディレクトリの扱い

Perlスクリプトを使用して、過去のブログ記事(SHIFT_JIS形式のHTML/TXTファイル)をUTF-8に変換し、本文やメタ情報を抽出してJSON化しています。これらのスクリプトは、データ整形の準備段階で一度だけ実行し、その後は変換済みのJSONをReact側で読み込んで表示に使っています。

UI/UX設計

  • 年代別ナビゲーションで大量コンテンツを整理
  • 最小限のインタラクションで直感的に操作できる構成

ディレクトリ構造

src/
  |- data/
  |   |- data.json
  |
  |- components/ (UIの一部を構成する再利用可能な部品)
  |   |- index.ts
  |   |- Header/
  |   |   |- Header.tsx
  |   |   |- Header.scss
  |   |- Footer/
  |   |   |- Footer.tsx
  |   |   |- Footer.scss
  |   |- YearList/
  |   |   |- YearList.tsx
  |   |   |- YearList.scss
  |   |- BlogDetail/
  |   |   |- BlogDetail.tsx
  |   |   |- BlogDetail.scss
  |
  |- styles/
  |   |- global.scss (全体共通のスタイル)
  |   |- utils/
  |   |   |- utils.scss
  |
  |- index.tsx
  |- index.scss
  |- App.tsx
  |- App.scss
  |
 scripts/
  |- convert_encoding.pl

src/contents/
  |- Blog/{year}/{month}/{date}/
  |   |- index.html   # 記事本文(旧ブログHTML)
  |   |- index.rss    # メタ情報(旧CMS由来)
  |- Bimages/{year}/
      |- xxx.jpg      # 記事で使われる画像

コンポーネント構成図

  • App.tsx をルートコンポーネントとし、Header・Footer・YearList・BlogDetail に分割
  • 各UI部品は components/ に整理し、再利用可能な形で設計

苦労したこと

すべてのHTMLファイルがSHIFT_JISで保存されていたため、まずはUTF-8への一括変換が必要でした。しかし、ChatGPTが提案した変換ツールではうまく変換できませんでした。最終的には以前使っていたPerlスクリプトを使うことにし、正規表現を組み合わせて変換と抽出を行いました。

ChatGPTのスクリプトでは思うように動かず、こちらが正しく伝えるためにも、Perlの文法や処理の流れを自分で学び直す必要がありました。試行錯誤に時間がかかり、この工程だけで10時間以上を要しました。

やり残し・今後の改善

今回の実装では、2004年以前のホームページのコンテンツには手をつけていません。留学中にまとめていた「American Jokes」や、東海岸から西海岸へ車で移動した記録「大陸横断記録」は、別ページとして構成すれば面白いと考えており、今後、小さな独立サイトとして分けて作ってみるかもしれません。

また、現在は静的な年別表示のみに留まっているため、検索機能を加えて、過去記事をたどれるようにするのもよさそうです。たとえば、キーワード検索(全文検索)には Fuse.js のような軽量ライブラリを使い、タグやカテゴリごとの絞り込み機能も追加するなどです。

まとめ

このプロジェクトは2023年に一度終えたものの、その後忙しくなったこともあり、独自ドメインでの公開まではできませんでした。ドメインの設定は夫に任せていますが、今回はGitHub Pagesで独自ドメインを設定する仕組みを、自分なりに理解したことは、大きな前進でした。

ただ、実際にページを作ったのが1年以上前だったため、今回このまとめを書くにあたって当時の作業内容を思い出すのが大変でした。今後は、作ったタイミングで技術的な記録もあわせて残すようにしたいと思います。

Discussion