·5 min read·alesion30.tech

個人ブログをリニューアルしました

ON THIS PAGE

はじめに

個人ブログをずっと放置していたのですが、ちゃんと整備しようと思い、この度大幅リニューアルしました。せっかくなので、記事として残しておこうと思います。

リニューアル前は、簡単なトップページと記事一覧、記事ページだけで構成していました。トップページには経歴とスキルを箇条書きし、記事一覧には自前記事と外部サービスに書いた記事を並べていました。

リニューアル前のHomeページ。HomeとBlogだけのナビゲーション、経歴とスキルの箇条書き、アバター、最新記事の一覧がある

情報は置いてありますが、どのような仕事をしていて、何に関心があり、何を作ってきたのかは伝わりにくい状態でした。普段使うAIに自分のことを理解してもらうための情報源としても使いたかったので、見た目だけでなく情報の集め方と渡し方から作り直すことにしました。

自分の情報を一か所に集める

記事はこのブログだけに書いているわけではありません。Zenn、Qiita、しずかなインターネットにも投稿しているので、単にリンクを並べるだけでは、投稿先ごとに活動が分かれてしまいます。

外部記事はクローラーで定期的に取得し、SQLiteに保存するようにしました。自前記事はMarkdown、外部記事はSQLiteと置き場所は違いますが、サイト側では同じPost型に揃えて、日付順にまとめて表示しています。

サイトのビルド時には、あらかじめクローラーで収集したSQLiteを読むだけです。外部サービスへアクセスしないため、ビルドを高速に実行できます。

sequenceDiagram
  participant GA as GitHub Actions<br/>毎日 6:00 JST
  participant C as Crawler<br/>Node.js / TypeScript
  participant Q as Qiita
  participant Z as Zenn
  participant S as しずかな<br/>インターネット
  participant DB as posts.db<br/>SQLite
  participant GH as GitHub
  participant B as Cloudflare<br/>Workers Builds
  participant W as Cloudflare<br/>Workers
  participant Site as alesion30.tech

  GA->>C: pnpm run crawl
  par 外部記事を取得
    C->>Q: 記事を取得
    C->>Z: 記事を取得
    C->>S: 記事を取得
  end
  C->>DB: 記事・タグを保存
  alt data/posts.db に差分あり
    C->>GH: commit / push
    GH->>B: ビルドを起動
    B->>DB: node:sqliteで読み出す
    B->>B: Markdownと統合して静的生成
    B->>W: 静的生成物をデプロイ
    W->>Site: 配信
  else 差分なし
    C-->>GA: コミットせず終了
  end

記事一覧の検索と絞り込みには、ビルド時に埋め込んだデータをクライアントサイドで使っています。ネットワークを待たずにフィルタリングできるので、タイトルやタグ、掲載先から素早く記事を辿れます。

Postsページの絞り込みUI。検索ボックス、タグのチップ、掲載先のフィルタが並んでいる

Claude Designで人間が辿れる画面を設計する

情報を集めるだけでは、サイトを見た人に人物像は伝わりません。トップページでは自己紹介と最新記事を、Aboutページでは経歴・スキル・実績を、Postsページでは活動を横断して探索できるように役割を分けました。

リニューアル後のHomeページ。ドット背景のヒーローとLATEST POSTSのカードグリッド

UIはClaude Designで作りました。各画面のデザインを作るだけでなく、Home / Posts / Article / Aboutの画面とあわせて、トークン、コンポーネントの状態、レスポンシブ規則、インタラクションも用意しました。

Design Tokensのページ。カラートークンの一覧とタイポグラフィのスケール

コンポーネントの状態一覧。ボタンやタグのhover・focus・disabledの見た目

画面を見て色や余白を目分量で実装するのではなく、設計をそのまま実装の入力として扱える状態になっていました。

Claude DesignをClaude Codeで実装する

実装はClaude CodeにClaude Design MCPをつないで進めました。プロジェクトの各ファイルを直接読めるので、スクリーンショットを見ながら色や余白を目分量で決める必要がありません。

トークンはglobal.cssに移植し、既存のディレクトリ構成に合わせてHTMLとCSSをui/配下のAstroコンポーネントへ分解しました。デザインと実装の画面が揃うまでgoalコマンドで反復したので、見た目は設計と同じ状態まで持っていくことができました。

ダークテーマの記事ページ。右側に目次、本文にmermaidの図が表示されている

デザインを実装可能な状態で受け取れたので、色や余白を合わせる作業よりも、外部記事をどう統合するか、関連記事をどう並べるか、テーマをどこに保存するかといったブログ固有の問題に時間を使うことができました。

AIが情報を辿る入口を作る

人間向けにはトップページやナビゲーションがありますが、AIには別の入口も用意しました。

/llms.txtには、サイトの説明、Home / Posts / Aboutへのリンク、最新20件の記事、RSS、サイトマップを置いています。記事本文を全件詰め込むのではなく、何があるサイトなのかを最初に渡すための索引です。

WebMCPもトップページに組み込みました。WebMCPは、Webページがブラウザ内のAIエージェントに対して構造化されたツールを公開するための提案中の仕様です。現時点では対応環境が限られ、仕様も変わる可能性がありますが、AIがこのサイトの情報をどの単位で読むべきかを明示する実験として使っています。

WebMCP Model Context Tool Inspectorで、alesion30.techが公開した読み取り専用ツールの一覧とget_profileの実行結果を確認している画面

現時点では、ローカルで動作を確認するために、Chromeの実験フラグchrome://flags/#enable-webmcp-testingを有効化して再起動し、Model Context Tool Inspectorを入れる必要があります。拡張機能では、ページが公開しているツールの一覧・入力スキーマ・出力を確認でき、手動呼び出しや自然言語プロンプトでWebMCPの動作を検証できます。

公開しているツールは下記の6つです。

  • get_profile — 名前、自己紹介、現在の役割、所属、拠点、SNS、RSSを取得する
  • get_skills — スキル領域、説明、関連技術を取得する
  • list_career / get_career_detail — 経歴の一覧と詳細を取得する
  • search_achievements — OSS、登壇、受賞を年・種別・キーワードで検索する
  • search_posts — 自前記事と外部記事をキーワード、タグ、掲載元で検索する

WebMCPのツールはブラウザで動きますが、記事一覧はビルド時にしかSQLiteを読めません。そのため、プロフィール、スキル、経歴、実績、記事をまとめたagent-context.jsonをビルド時に生成し、ツールが最初に呼ばれたときだけ取得するようにしています。通常の閲覧では追加の通信は発生しません。

おわりに

人間には画面と導線を、AIには索引と構造化されたツールを用意しました。今後も記事や実績を追加しながら、公開できる自分のコンテキストとしてこのブログを育てていきたいなと思っています。

参考URL