▲ Vercel ☁ Cloudflare Workers SQLite D1 OKF v0.2

FONT-LOVER
Webフォント探検ツール

Webサイトから使用されているフォントを自動検出し、ディストリビューションデータベースとして閲覧・分析できるオープンソースツールです。OKF v0.2 準拠の知見バンドルを自動生成します。

なぜ FONT-LOVER が必要か

Webデザインにおいてフォント選択は重要な意思決定の一つですが、他サイトでどのようなフォントが実際に使用されているかを体系的に把握する手段は限られていました。

🔍

手動調査の限界

ブラウザの開発者ツールで1サイトずつ確認する必要がある。大量のサイトを横断的に分析することは困難です。

📊

データの分散

Google Fonts の人気ランキングと、実際のWebサイトでの使用率にはギャップがある。実際の採用データを収集する仕組みが必要です。

📚

知見の形式化

フォントに関する知識を機械可読な形式で整理し、再利用可能な形に保つ仕組みがありませんでした。

システムアーキテクチャ

3層構成のマルチクラウドアーキテクチャ。GitHub でソースを管理し、Vercel でフロントエンド、Cloudflare Workers + D1 でデータ収集と保存を担当します。

SYSTEM ARCHITECTURE 🌐 ユーザーのブラウザ font-lover.vercel.app HTTPS POST /api/scan VERCEL Next.js App Router Zine (UI) /okf, /inspector API Routes /api/fonts, /api/okf lib/data.ts REMOTE 切替レイヤ 📄 pipeline/knowledge/*.json (コミット済みOKF v0.2 バンドル) COLLECTOR_URL Bearer Token 認証 CLOUDFLARE Workers (無料枠) Light Scan HTML regex 抽出 Store drizzle ORM GET APIs fonts/sites/stats D1 font-lover-db 🗄️ Cloudflare D1 font_families / font_faces / font_sightings / font_mdn_refs APAC リージョン・無料枠 🐙 GitHub watanabe3tipapa/font-lover mono-repo (collector + zine + database + shared-types) push → Vercel 自動デプロイ / wrangler deploy → Workers git push ⚙️ gen-okf.mjs → pipeline/knowledge/ Vercel (zine) Cloudflare (collector) D1 (データベース) OKF 知識バンドル GitHub (ソース管理)

図: マルチクラウド3層構成。ユーザーは Vercel 上の UI (zine) を使い、データは Cloudflare D1 に集約される。
ローカル開発時は better-sqlite3 で直接操作し、本番は COLLECTOR_URL 経由のプロキシに切り替わる。

仕組みを詳しく

スキャン、保存、表示の3つのフェーズで構成されています。

1 スキャンフェーズ

SCAN FLOW — lightScan() POST /api/scan {"url":"...", "mode":"light"} fetch(url) HTML を取得 Regex 抽出 @font-face { ... } font-family: ... Google Fonts 検出 fonts.googleapis.com ?family=... を抽出 Response DetectedFont[] 抽出パターン @font-face\{...\} font-family:\s*([^;}{]+) fonts\.googleapis\.com ...family=([^&"']+) HTML のみ解析(CSS 読み込み無し) storeScanResult で保存 ① font_families に UPSERT(重複時 popularity +1) ② font_sightings に INSERT(サイトURL + モード) ③ font_faces に INSERT(@font-face SRC がある場合) source_type は "google-fonts" / "unknown" 等に自動分類

2 データ保存フェーズ

DATA SCHEMA — D1 / SQLite font_families id INTEGER PK family_name TEXT UNIQUE category TEXT source_type TEXT popularity REAL ← 観測回数でスコア付け font_sightings id INTEGER PK family_id INTEGER FK site_url TEXT site_domain TEXT mode TEXT ← light / full font_faces id INTEGER PK family_id INTEGER FK weight TEXT style TEXT source_url TEXT ← @font-face src font_mdn_refs id INTEGER PK family_id INTEGER FK mdn_slug TEXT description TEXT compat_note TEXT ← MDN ブラウザ互換情報 1:N 1:N 1:N

3 表示フェーズ(プロキシ切替)

💻 ローカル開発

  • better-sqlite3 で ./font-lover.db を直接参照
  • lib/db.ts の遅延初期化でモジュール読み込み時クラッシュ防止
  • リアルタイムで DB の変更が即座に反映される
  • OKF ビューワーは buildOkfKnowledge() でライブ生成
  • COLLECTOR_URL 未設定 → ローカルモード

☁️ 本番 (Vercel)

  • lib/data.tsCOLLECTOR_URL を検出しプロキシに切替
  • GET /api/fonts 等 → Cloudflare Worker 経由で D1 を参照
  • Worker 側は Bearer Token 認証で不正アクセスを防止
  • OKF ビューワーはコミット済み pipeline/knowledge/*.json を返す
  • DB 不在でも空データ / フォールバックで UI が崩れない
DATA ACCESS — lib/data.ts ルーティング API Route / Page listFonts() / getStats() lib/data.ts if (REMOTE) → proxy else → getDb() lib/db.ts → better-sqlite3 proxyFetch() Bearer + cache: no-store Cloudflare Worker GET fonts / sites / stats D1 SELECT → JSON proxySafe → エラー時は空データ返却

知見バンドル自動生成パイプライン

OKF (Open Knowledge Format) v0.2 準拠の JSON バンドルを、DB の蓄積データから自動生成します。

🗄️ D1 / SQLite

font_families
font_sightings
font_mdn_refs

⚙️ buildOkfKnowledge()

Drizzle ORM で
全テーブルを結合クエリ

📊 hash 差分

前回バンドルと比較
new / updated / unchanged

📄 JSON 生成

index.json
concepts/fonts/*.json

🌐 /api/okf

okf_version: "0.2"
machine-readable

{
  "okf_version": "0.2",
  "index": {
    "generatedAt": "2026-09-14T06:30:24.195Z",
    "total": 7,
    "byStatus": { "new": 3, "unchanged": 4 },
    "concepts": [
      { "id": "fonts/inter", "type": "FontFamily",
        "status": "new", "sections": 3 },
      { "id": "fonts/noto-sans-jp", "type": "FontFamily",
        "status": "unchanged", "sections": 3 }
    ]
  },
  "concepts": [
    {
      "id": "fonts/inter",
      "type": "FontFamily",
      "title": "Inter",
      "url": "https://fonts.google.com/specimen/Inter",
      "meta": {
        "type": "FontFamily",
        "tags": ["sans-serif", "google-fonts"],
        "generated": {
          "by": "process:font-lover-collector/0.1.0",
          "at": "2026-09-14T06:30:24.195Z"
        },
        "verified": true,
        "stale_after": "2026-12-13T06:30:24.195Z",
        "sources": [
          { "site": "vercel.com", "usage_count": 5 }
        ]
      },
      "sections": [
        { "heading": "Summary", "level": 2,
          "blocks": [{ "type": "text",
            "content": "Inter は 25 sight..." }] },
        { "heading": "Sightings", "level": 2,
          "blocks": [{ "type": "list", "items": [
            "vercel.com (×5)",
            "techcrunch.com (×3)"
          ]}] }
      ],
      "hash": "a1b2c3d4..."
    }
  ]
}

図: /api/okf のレスポンス例。各 concept には sightings から要約した section が含まれ、meta.stale_after でリフレッシュ時期を示す。

技術スタック

Vercel

Next.js App Router / Edge Runtime

Cloudflare Workers

Hono / nodejs_compat / 無料枠

🗄

Cloudflare D1

SQLite ベースのエッジDB / APAC

TypeScript

TypeScript

全体を strict で型安全に

Drizzle

Drizzle ORM

SQLite / D1 共通のスキーマ定義

Turbo

Turborepo

monorepo ビルドキャッシュ

pnpm

pnpm

workspace パッケージ管理

Hono

Hono

超軽量 Web フレームワーク

政府サイトの採集記録

2026-09-14、日本の中央省庁・機関 39サイトを light スキャンし、実際に使われているフォントを採集しました。

39 サイト採集 7 フォント検出 2026-09-14
🇯🇵

Noto Sans JP

デジタル庁 / 総務省 / 首相官邸系サイトで標準採用。公的サイトの定番であることを実測で確認。

🀄

Noto Serif JP

首相官邸の見出しで使用。セリフ体がフォーマルな文書表現に使われる実例。

📖

BIZ UDPGothic

文化庁で検出。国産ユニバーサルデザイン書体が行政サイトでも採用されている。

M PLUS Rounded 1c

こども家庭庁で検出。丸ゴシックの親しみやすいトーンを選択する事例。

採集データは /api/sites/:domain からサイト別に参照できます。

デモ

Vercel でホストされている本番環境を直接お試しいただけます。

font-lover.vercel.app
↗ フルスクリーンで開く /api/fonts /api/stats /api/okf OKF ビューワー DBインスペクタ

API リファレンス

Cloudflare Worker(collector)

Endpoint: https://font-lover-collector.watanabe3ti.workers.dev — Bearer Token 認証必須

MethodPath説明レスポンス
POST/api/scanURL をスキャンし D1 に保存{url, mode, fonts[], fontFaces[]}
POST/api/collect複数 URL を一括スキャン{results[], processed, failed}
GET/api/fonts全フォントファミリを取得(人気順){fonts[]}
GET/api/fonts/:family特定フォントの詳細 + sighting{font, sightings[]}
GET/api/sites/:domain特定ドメインで検出されたフォント{fonts[]}
GET/api/stats統計情報(件数・ランキング等){totalFonts, totalSightings, topFonts[]}
GET/ヘルスチェック{ok: true}

Vercel(zine)

Endpoint: https://font-lover.vercel.app

MethodPath説明動作
GET/api/fontsフォント一覧本番: Worker → D1 / ローカル: SQLite
GET/api/fonts/:familyフォント詳細同上
GET/api/sites/:domainサイト別フォント同上
GET/api/stats統計情報同上
GET/api/okfOKF v0.2 知識バンドルコミット済み JSON / ローカル: ライブ生成
GET/okfOKF ビューワー(UI)
GET/inspectorDB インスペクタリモート: リンク集 / ローカル: JSON 表示

チュートリアル

2つの方法で FONT-LOVER をお試しいただけます。

A. API を使ってサイトをスキャンする

Worker URL とトークンを用意する

Worker のエンドポイントと、認証に使う Bearer Token を確認します。ローカルで動作させている場合は http://localhost:8787.dev.vars のトークンを使います。

POST /api/scan でスキャン

対象の URL を送信します。

curl -X POST https://font-lover-collector.watanabe3ti.workers.dev/api/scan \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com","mode":"light"}'

GET /api/fonts で結果を確認

保存されたフォント一覧を取得します。

curl https://font-lover.vercel.app/api/fonts | jq '.fonts[0:3]'

OKF バンドルを閲覧する

/okf で、全フォントの知見を体系的に閲覧できます。

B. ローカルで開発環境を構築する

リポジトリをクローン

git clone https://github.com/watanabe3tipapa/font-lover.git
cd font-lover
pnpm install

collector を起動(wrangler dev)

ローカル D1 にスキーマを適用してから起動します。

# プレーン SQL に変換(statement-breakpoint を除去)
grep -v -- '-->' packages/database/drizzle/0000_unusual_nextwave.sql > /tmp/schema.sql

# ローカル D1 にスキーマ適用
npx wrangler d1 execute font-lover-db --local --file=/tmp/schema.sql

# collector 起動(port 8787)
npx wrangler dev --port 8787

zine を起動

プロキシモードで起動する場合:

# 本番モード(D1 プロキシ)で起動
COLLECTOR_URL=http://localhost:8787 pnpm --filter @font-lover/zine dev

# ローカル SQLite モードで起動
pnpm --filter @font-lover/zine dev

スキャン → 確認

# スキャン
curl -X POST http://localhost:8787/api/scan \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com","mode":"light"}'

# 確認
open http://localhost:3000/api/fonts

自分で運用する

無料アカウントだけで本番環境を構築する手順です。

1

GitHub リポジトリを fork

watanabe3tipapa/font-lover を fork します。

2

Cloudflare で Worker + D1 を作成

wrangler loginwrangler d1 create font-lover-db → 得られた database_id を wrangler.toml に反映。

3

スキーマ適用 → デプロイ

wrangler d1 execute ... --remote --file=schema.sqlwrangler deploy

4

Vercel にデプロイ

Vercel で GitHub リポジトリを紐付け。Root Directory を apps/zine に設定。

5

環境変数を設定

Vercel に COLLECTOR_URLWORKER_TOKEN を設定。Worker にも WORKER_TOKEN をシークレットとして登録。

6

スキャン開始

Token 認証付きで POST /api/scan → フォントデータが蓄積されていきます。

無料枠の目安

Cloudflare Workers: 100,000 req/day • D1: 5 GiB ストレージ • Vercel: 100 GB バンド幅/月
※ Browser Rendering(フルスキャン)は有料プラン (Workers Paid $5/月) が必要です。