この記事は、Qiitaユーザーの活動を1枚の自己完結型SVGにまとめて表示するサービス Qiita Glyph の実装を詳細に解説する技術記事です。
概要
Qiita Glyph は以下のようなサービスです。
- Qiita APIからユーザー情報と投稿を取得する。
- 投稿数、LGTM、Stocks、フォロワー数を集計し、SVGで一枚にまとめる。
- READMEやブログに簡単に埋め込める。
- ライト/ダークのテーマ切替に対応。
- Cloudflare Workers上で高速に運用し、キャッシュでAPI呼び出しを抑制する。
この実装は TypeScript(Honoフレームワーク)で書かれ、Cloudflare Workersのエッジで動作することを想定しています。
実装の解説
アーキテクチャ
-
クライアントがGETリクエスト
-
エッジ(Cloudflare Workers)がキャッシュを参照(
caches.default) -
キャッシュなしの場合:
- Qiita APIからユーザー情報を取得。
- ページネーション(per_page=100)で全アイテムを取得。
- 投稿数・LGTM合計・Stocks合計・Followersを集計。
- プロフィール画像をフェッチしてBase64化(SVGに埋め込み)。
- SVGを生成してレスポンス→キャッシュに保存。
-
エラー時はSVGでエラーメッセージを返す(読み込み側で破綻しないようにするため)
主要な実装ポイントと設計判断
1) API呼び出しの失敗を示す方法
- APIエラーでも常にSVGを返す(
Content-Type: image/svg+xml)。READMEやブログで表示される際、画像の破綻やBroken imageにならないようにするためです。 - HTTPステータスは適切に設定(404, 429など)しつつ、SVG本文内で人が読めるエラーメッセージを埋め込みます。
2) キャッシュ戦略(Cloudflare Workers)
-
caches.defaultを利用して、リクエストURL(themeを含む)をキーにキャッシュします。これによりライト/ダークが混在してキャッシュ汚染するのを防止します。 -
レスポンスヘッダー例:
"Cache-Control": "public, max-age=0, s-maxage=86400, stale-while-revalidate=86400"-
s-maxage=86400によってエッジで1日キャッシュ。 -
stale-while-revalidateを併用し、古いキャッシュを即時返しつつバックグラウンドで再検証(Workers側でのfetchが発生)する運用を想定。
-
-
注意点:Qiita APIのレート制限に注意。キャッシュが効く設計は必須です。
3) プロフィール画像の扱い
-
実装はプロフィール画像を
data:[content-type];base64,...に変換してSVGに埋め込んでいます。- 利点:外部リソースに依存しない、READMEに貼ったときに画像が常に表示される。
- 欠点:画像をBase64化するとSVGのサイズが増える(転送量増)。頻繁に画像が変わるユーザーには不利。
-
実装では
Bufferの存在を確認して高速にBase64化し、存在しない環境ではbtoaにフォールバックする互換処理を入れています。
4) セキュリティ:SVG内のエスケープ
- ユーザー名やユーザーIDをSVGに埋め込む際は
escapeXmlを常に通して、HTML / SVGインジェクションを防ぎます。 -
clipPathやid属性はmakeSafeIdでサニタイズ([^a-zA-Z0-9_-]を_に置換)し、SVG内でのID衝突や不正な属性を予防します。
5) ページネーションの取り回し
-
現在の実装は
per_page=100&page=Nを順にループで取得する方式(最初から最後まで順次フェッチ)。- シンプルで確実だが、投稿数が数百〜千近いユーザーではQiita APIへの多数の呼び出しが発生する可能性がある。
使い方
以下の形式でURLを作成するだけで、自分のQiita活動をSVG化できます。
https://qiita-glyph.yosshy-123.workers.dev/[user_id]
-
[user_id]を自分のQiitaユーザーIDに置き換えます。 - デフォルトはライトテーマです。
URLに ?theme=dark を追加するとダークテーマで表示できます。
https://qiita-glyph.yosshy-123.workers.dev/[user_id]?theme=dark
例
ライトテーマ
[](https://qiita.com/Yosshy_123)
ダークテーマ
[](https://qiita.com/Yosshy_123)
まとめ
Qiita Glyphを使えば、自分のQiita活動を簡単に可視化してシェアできます。
READMEやブログに埋め込んで、自分のアウトプットをアピールしてみましょう。