Quartz運用改善メモ: Private運用・Cloudflare Workers・OG・検索UX

このノートは、note-zk(コンテンツ)+ note-zk-quartz(配信)の現行運用を、後から再現・引き継ぎできるようにコードベースで整理したもの。


0. 現在の運用アーキテクチャ

  • note-zk(private)
    • ノート本体
    • push時に note-zk-quartz の deploy workflow を dispatch
  • note-zk-quartz(private)
    • Quartz v4 本体
    • CIで note-zk を checkout して content/ に同期
    • Quartz build して Cloudflare Workers に deploy
  • 本番URL
    • https://notes.koei-lab.org

1. Cloudflare Workers デプロイ(GitHub Pages廃止)

1-1. 変更ファイル

  • note-zk-quartz/.github/workflows/deploy.yaml
  • note-zk-quartz/quartz.config.ts

1-2. quartz.config.ts の重要値

configuration: {
  pageTitle: "Koei's Digital Garden",
  baseUrl: "notes.koei-lab.org",
}

1-3. deploy workflow の要点

- name: Build Quartz
  run: npx quartz build
 
- name: Deploy to Cloudflare Workers (static assets)
  uses: cloudflare/wrangler-action@v3
  with:
    apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
    accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
    wranglerVersion: "4"
    command: deploy --assets=public --name=${{ secrets.CLOUDFLARE_WORKER_NAME }} --compatibility-date=2026-03-10

1-4. 必須 Secrets(note-zk-quartz

  • ZK_REPO_TOKENnote-zk read)
  • CLOUDFLARE_API_TOKEN
  • CLOUDFLARE_ACCOUNT_ID
  • CLOUDFLARE_WORKER_NAME

2. private repo運用を安定化(submodule依存を回避)

2-1. 背景

content submodule を deploy 環境で直接更新すると認証トラブルが起きやすい。 そのため「CIで明示checkout→content同期」に切り替えた。

2-2. deploy workflow 実装

- name: Checkout note-zk-quartz
  uses: actions/checkout@v4
 
- name: Checkout note-zk content (private)
  uses: actions/checkout@v4
  with:
    repository: koei-kaji/note-zk
    ref: main
    token: ${{ secrets.ZK_REPO_TOKEN }}
    path: .content-src
 
- name: Replace Quartz content with note-zk
  run: |
    rm -rf content
    mkdir -p content
    rsync -a --delete --exclude='.git' .content-src/ content/

2-3. note-zk 側の dispatch

変更ファイル:

  • note-zk/.github/workflows/trigger-deploy.yaml

要点:

on:
  push:
    branches: [main]
 
# note-zk-quartz の deploy.yaml を workflow_dispatch

必要 secret(note-zk):

  • DEPLOY_TOKEN

3. 左サイドバー構成の改善(Explorer + Archive)

3-1. 変更ファイル

  • note-zk-quartz/quartz.layout.ts
  • note-zk-quartz/quartz/components/Archive.tsx
  • note-zk-quartz/quartz/components/styles/archive.scss
  • note-zk-quartz/quartz/components/index.ts

3-2. Explorer フィルタ

const omit = new Set(["FleetingNotes", "LiteratureNotes", "AGENTS", "tags"])

3-3. Explorer アイコン表示

mapFn: (node) => {
  if (node.isFolder) node.displayName = "📁 " + node.displayName
  else node.displayName = "📄 " + node.displayName
}

3-4. Archive(年別件数)

  • 左サイドバーに Archive を追加
  • 表示順は降順(新しい年→古い年)
  • draft: true は除外

4. トップページ導線(低保守)

4-1. 方針

  • index.md は手入力更新を増やさない
  • 最小固定情報 + 自動更新情報だけにする

4-2. 実装

  • note-zk/content/index.md(= note-zk の index.md)は最小化
  • quartz.layout.tsafterBody で index限定 RecentNotes を表示
Component.ConditionalRender({
  component: Component.RecentNotes({
    title: "Recent Notes",
    limit: 5,
    showTags: true,
    showDate: true,
    showDirectory: true,
    filter: (page) => ...
  }),
  condition: (page) => page.fileData.slug === "index",
})

5. OGP / Twitter Card 改善

5-1. 変更ファイル

  • note-zk-quartz/quartz.config.ts
  • note-zk-quartz/quartz/util/og.tsx
  • note-zk-quartz/quartz/static/og-image.png
  • note-zk-quartz/quartz/static/icon.png

5-2. 実装内容

  1. デフォルトOG画像を配置
  2. CustomOgImages を有効化(ノートごとに title/description から自動生成)
  3. icon差し替え
  4. 日本語文字化け対策で Noto Sans JP フォールバックを追加

quartz.config.ts:

Plugin.CustomOgImages({
  colorScheme: "darkMode",
})

og.tsx(要点):

  • getSatoriFonts()Noto Sans JP を追加
  • title/body の fontFamilyNoto Sans JP をフォールバック指定

6. Search UX(日本語IME Enter問題)

6-1. 変更ファイル

  • note-zk-quartz/quartz/components/scripts/search.inline.ts

6-2. 修正内容

Enter時に IME 変換中なら検索実行しない。

if (e.key === "Enter") {
  if (e.isComposing || (e as KeyboardEvent).keyCode === 229) return
  // 検索実行
}

7. Search Console 初期セット

  1. https://notes.koei-lab.org/ を対象に所有権確認
  2. sitemap.xml 送信
  3. ドメイン表記ゆれ (koei-lab.org / koei-labs.org) を避ける

確認URL:

  • https://notes.koei-lab.org/sitemap.xml

8. トラブルシューティング記録(実際に発生)

A. --name= 空で wrangler 失敗

  • 原因: CLOUDFLARE_WORKER_NAME 未設定
  • 対策: workflow冒頭に secret バリデーションを追加

B. compatibility_date is required

  • 原因: wrangler v4 で必須
  • 対策: deploy command に --compatibility-date=2026-03-10

C. OGP 日本語文字化け

  • 原因: OG生成フォントに日本語グリフ不足
  • 対策: Noto Sans JP 追加

9. 追加改善(2026-03-11 午前対応)

9-1. Archive をクリック可能にして年別一覧へ遷移

変更ファイル

  • note-zk-quartz/quartz/components/Archive.tsx
  • note-zk-quartz/quartz/plugins/transformers/archiveYearTag.ts
  • note-zk-quartz/quartz/plugins/transformers/index.ts
  • note-zk-quartz/quartz.config.ts

実装内容

  1. build時に archive-YYYY タグを自動付与する transformer を追加
// quartz/plugins/transformers/archiveYearTag.ts
const allowed = [
  "PermanentNotes/",
  "LiteratureNotes/",
  "StructureNotes/",
  "SourceNotes/",
]
if (!allowed.some((prefix) => slug.startsWith(prefix))) return
 
const year = d.getFullYear()
const tag = `archive-${year}`
  1. Archive コンポーネントのバッジをリンク化
const slug = `tags/archive-${year}` as FullSlug
<a href={resolveRelative(fileData.slug!, slug)} class="internal archive-badge">
  {year}({count})
</a>
  1. Archive 集計対象を 4ディレクトリに限定
const allowed = ["PermanentNotes/", "LiteratureNotes/", "StructureNotes/", "SourceNotes/"]
if (!allowed.some((prefix) => slug.startsWith(prefix))) continue

バグ修正履歴

  • tags/tags/archive-2025 になる不具合を修正
    • 原因: resolveRelative("index", slug) で固定解決していた
    • 対策: resolveRelative(fileData.slug!, slug) に変更

9-2. Folder/Tag 一覧の可読性改善(Recent Notes寄せ)

変更ファイル

  • note-zk-quartz/quartz/components/PageList.tsx
  • note-zk-quartz/quartz/components/styles/listPage.scss

実装内容

  • タグ表示を右列の縦積みから、タイトル下の折り返し表示へ変更
  • 各ノートに保存先ディレクトリバッジを表示
  • archive-YYYY タグは一覧表示から除外(ノイズ削減)

PageList.tsx 主要差分:

const tags = (page.frontmatter?.tags ?? []).filter((tag) => !tag.startsWith("archive-"))
const directory = page.slug ? page.slug.split("/")[0] : null
 
{directory && (
  <p class="directory">
    <span class="directory-badge">{directory}</span>
  </p>
)}
 
<ul class="tags"> ... </ul>

listPage.scss 主要差分:

& > .section {
  grid-template-columns: fit-content(8em) 1fr;
}

9-3. Home リンクに保存先ディレクトリを明示

変更ファイル

  • note-zk/index.md

実装内容

- [[StructureNotes/|Structure Notes]] — `StructureNotes/`
- [[PermanentNotes/|Permanent Notes]] — `PermanentNotes/`
- [[LiteratureNotes/|Literature Notes]] — `LiteratureNotes/`
- [[SourceNotes/|Source Notes]] — `SourceNotes/`

10. 運用時チェックリスト

  • baseUrl と本番ドメインが一致している
  • note-zk push で note-zk-quartz deploy が連鎖起動する
  • OGP表示が更新されない場合、SNS側キャッシュを再取得する
  • workflow更新時、利用トークンに workflow スコープがある
  • Archive の件数と tags/archive-YYYY 一覧に index/AGENTS 等が混入していない

一言まとめ

今回の改善で、Quartz運用は「手動更新依存を増やさずに、公開品質と再現性を維持する」形に収束した。今後はこのノートを実装の正本として、設定変更は必ずここへ追記する。