0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

READMEに貼れるQiita活動メーター『Qiita Glyph』を作った話

0
Last updated at Posted at 2026-01-15

この記事は、Qiitaユーザーの活動を1枚の自己完結型SVGにまとめて表示するサービス Qiita Glyph の実装を詳細に解説する技術記事です。

概要

Qiita Glyph は以下のようなサービスです。

  • Qiita APIからユーザー情報と投稿を取得する。
  • 投稿数、LGTM、Stocks、フォロワー数を集計し、SVGで一枚にまとめる。
  • READMEやブログに簡単に埋め込める。
  • ライト/ダークのテーマ切替に対応。
  • Cloudflare Workers上で高速に運用し、キャッシュでAPI呼び出しを抑制する。

この実装は TypeScript(Honoフレームワーク)で書かれ、Cloudflare Workersのエッジで動作することを想定しています。

実装の解説

アーキテクチャ

  1. クライアントがGETリクエスト

  2. エッジ(Cloudflare Workers)がキャッシュを参照(caches.default

  3. キャッシュなしの場合:

    • Qiita APIからユーザー情報を取得。
    • ページネーション(per_page=100)で全アイテムを取得。
    • 投稿数・LGTM合計・Stocks合計・Followersを集計。
    • プロフィール画像をフェッチしてBase64化(SVGに埋め込み)。
    • SVGを生成してレスポンス→キャッシュに保存。
  4. エラー時は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インジェクションを防ぎます。
  • clipPathid 属性は 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

ライトテーマ

Qiita Glyph

[![Qiita Glyph](https://qiita-glyph.yosshy-123.workers.dev/Yosshy_123)](https://qiita.com/Yosshy_123)

ダークテーマ

Qiita Glyph

[![Qiita Glyph](https://qiita-glyph.yosshy-123.workers.dev/Yosshy_123?theme=dark)](https://qiita.com/Yosshy_123)

まとめ

Qiita Glyphを使えば、自分のQiita活動を簡単に可視化してシェアできます。
READMEやブログに埋め込んで、自分のアウトプットをアピールしてみましょう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?