garden.ooo Devlog
TODO
- Markdownエディタが若干重い
- MDエディタよこはみだし
- MDモバイルみぎスプリットいらん
-

- admin専用の
modifiedフィールド- admin認証下のmutationでだけサーバースタンプ。garden-ooo側の自動編集(リネーム等)では更新しない
- 保持先:
content_id → modifiedのマップをDB側に別途持つ。frontmatterには書かない(source_hash汚染を避ける) - ローカルバックアップ:
.garden/modified.jsonに debounce + atomic rename で書き出し。reset / 初回DB構築時にのみ読み込む一方向同期、差分検知なし - DataView の
sortByキーに追加(types/query.ts:135の enum)。一般 / ログインユーザーからは不可視で、指定された場合はupdatedに自動フォールバック
- 内部リンクのバックリンク時アンカージャンプ
- パース時、内部リンクを含むブロックに block-level anchor を付与し、バックリンクURL を
?p=source#b-XXXX形式にする - アンカー単位は per-block(per-link ではない)。AST を登って最初の block 相当ノードに振る
- custom prose-component(DataView 等の block-level)は コンポーネント自身を1ブロックとみなす。component の root に
idを forward する規約。inline component の場合は更に上の block 祖先まで登る - ハッシュ算出: ブロック正規化テキストの短縮ハッシュ(8文字程度)。段落編集で外れた場合はベストエフォート(ページ先頭にスクロール)で許容
- links テーブルは
(source_id, target_id, block_anchor)の単位で記録。同一ページ内の同一ターゲット複数参照は別行
- パース時、内部リンクを含むブロックに block-level anchor を付与し、バックリンクURL を
- ページ単位の changelog コンポーネントとフィード表示
::changelog{at="..." version="..."}MDC コンポーネント。defaultスロット = 単独ページとフィード両方に出る本文- props:
at(基本必須、未指定時はpage.modified(admin 専用 modified が出来たらそちら)にフォールバックし warn)、version(optional, MVPでは無くてもOK)、title(optional plain text, 未指定時はat+ version から自動生成) - パース時に
changelog_entries相当を DB へ事前抽出:(page_id, at, version, title, default_html, default_md)。source_hashベースの reconcile に乗せる - 表示用に専用コンポーネント
<ChangelogFeed>。クエリインターフェースは DataView と揃える(from,where,related-of等)。1エントリ=1カード形式で[date] [v-badge?] [title]+ 本文snippet <ChangelogFeed related-of="this">で frontmatterrelatedを辿って関連ページの changelog をまとめる用途を想定- 同じクエリを
?format=rssで RSS 出力できる設計に最初から寄せる
- per-site secret 管理基盤(Secret Registry パターン)
- 用途: WP/Cloudinary 等のメディアアップロード鍵、OAuth app credentials(GitHub Sponsors 等)、SMTP、その他将来の per-site 第三者サービス credentials を一元化
- runtimeConfig に置く secret は
SITE_SECRET_KEY(32byte AES master key)の1個のみ。それ以外の credentials は admin UI から入力 → 暗号化して DB へ - 3要素構成:
- Registry(コード):
server/secrets/registry.tsに namespace ごとに{ schema: zod, label, test?: async fn }を登録。namespace 規約は<category>.<provider>[.<role>](例:media.wordpress,oauth.github-sponsors.app) - Storage:
site_secretscollection(MongoDB only, client RxDBには乗せない)。{ _id: namespace, key_version, ciphertext: AES-256-GCM(iv, payload, tag), updated_at, updated_by } - Accessor: server-side
getSecret(namespace)で typed object を返す。in-memory キャッシュ(TTL ~5min)+ 更新時 invalidate
- Registry(コード):
- Admin UI: registry を introspect してフォーム自動生成。
schemaから zod-derived form、test関数があれば接続テストボタン、updated_at表示 - OAuth は2層: app credentials(
oauth.<provider>.app)は site_secrets、user token(access/refresh)は別 collectionuser_oauth_tokens(per-user ライフサイクル分離)。暗号化は同じ master key で OK - 段階的ロールアウト:
- Phase 1: 基盤(registry + collection + accessor + UI)を作り、既存
.envの WP credentials を移行 - Phase 2: OAuth app credentials を registry 化(GitHub Sponsors 等)
- Phase 3: 暗号化された backup の export/import を admin UI に追加(DB reset 時の再入力回避)
- Phase 1: 基盤(registry + collection + accessor + UI)を作り、既存
- その他:
key_versionフィールドは最初から持つ(rotation は後実装)。値はログに出さない、updated_byのみ監査用に残す
- マルチプロバイダの monetization / メンバーシップ基盤
- GitHub Sponsors だけでなく、Patreon / Gumroad / Stripe / Lemon Squeezy 等を併用できる抽象化
- 単品購入(per-content)と subscription tier の両方をサポート、訪問者が progressive にエンゲージできる導線(単品 → サブスク のアップセル等)
- provider 中立な「Entitlement」概念に集約し、ページの frontmatter
paywall: any_of: [...]で provider 横断で OR 評価 - 各 provider は adapter として実装(OAuth / license key / webhook など各々の流儀を吸収)。adapter の credentials は前述の Secret Registry に乗せる
- 同期戦略は provider ごとに webhook / pull-on-demand を使い分け、結果を server-only
entitlementscollection に正規化保存
- 2カラム Markdown エディタの廃止 → TipTap.dev ベースの単一エディタへ移行
2026-04-12
音声配信機能をつけた。
2026-04-01
詰め方の問題で触れられていたSkylineアルゴリズムをDataViewに実装した
2026-03-30
うれピ
2026-03-29
I'm tinkering with the new visual identity
![]()

2026-03-25
文字数カウント用のカスタム要素を作った もろもろの応募に便利

2026-03-17
garden.oooの同期実装がバイブス過ぎて、定期的に全ページの1割が勝手に消えるのを復元している