情報設計
コンテンツパイプライン
ページの「本体」は Markdown のソースコードではなく、HTML の AST(抽象構文木)。
現在は Nuxt MDC の MDCRoot を AST フォーマットとして使っているけれど、ここは差し替え可能な設計になっている。unified エコシステムを使えば、Markdown に限らず HTML にパース可能な任意の軽量マークアップ言語をサポートできる。
サーバーが保持するのは {source: string, body: AST, ...metadata} の組。AST の生成はクライアントサイドで行う。
この設計がもたらすもの:
- Copy as Markdown: AST → Markdown の逆変換
- PDF エクスポート: permanent ページの永続的な文書化
- カスタムパーサー: ユーザーが独自の記法を持ち込める
識別子の3層構造
ページには3種類の識別子がある。それぞれ異なる文脈で使う。
| 識別子 | 用途 | 例 |
|---|---|---|
path | ローカルのファイルパス。空白や記号をそのまま含む | Articles/100% User Supported |
uri | URL として使える形式。空白→_、制御文字→エスケープ | Articles/100%25_User_Supported |
slug | DB 検索用の正規化キー。uri.toLowerCase() | articles/100%25_user_supported |
変換は path → uri → slug の一方向。逆変換は uri → path(_ → 半角スペース)のみ可能。
slug が重複するページは作成できない。ローカルで衝突が起きた場合、後から検知された方はリネームされるまでリモートに同期されない。
関連コード:
utils/normalizeIdentifiers.ts— 識別子の変換sanitizeTitleToPath— パスのサニタイズnormalizeToSlug— slug の正規化
リンクとバックリンク
ページ同士の関連性はリンクで表現する。種類は2つ。
Tag link と Body link
- Tag link(
A is B): frontmatter のtagsで指定。所属・包摂・共通性 - Body link(
A refers to B): 本文中のハイパーリンク。言及・参照
Tag link のほうが強い関連性を示す。
バックリンク
A → B のリンクがあるとき、B のページに「関連ページ」として A を自動表示する仕組み。有向グラフとしてのハイパーリンクを双方向にしている。
これで従来 CMS の「カテゴリ一覧」を代替できる。「チーム」というページに、メンバーの各ページから tag link を貼って、レイアウトを grid にすれば、チームメンバー一覧ページになる。grid / table レイアウトでは body link のバックリンクが除外されるので、「チームについてはこちら!」みたいな無関係なページが混ざらない。
関連コード:
utils/markdown/collectOutlinksFromPage.ts— アウトリンク収集types/page.tsのLink—{type: 'tag' | 'link', slug: string}
公開範囲(Visibility)
4段階ある。
public: 誰でも見える。リストに表示されるunlisted: URL直打ちか直リンクでのみ到達可能。リスト表示やバックリンクには現れない。「文脈を追わないとたどり着けない」状態を作るprotected: 認証(パスワード、OAuth 等)が必要。メンバーシップ制の限定コンテンツや有料配信(note/Substack 的な)を想定している。決済機能は未実装private: 書き手だけが見える
関連コード: types/page.ts の visibilitySchema
Permanent フラグ
公開範囲とは別軸で、すべてのページが持つフラグ。永続化したいものとエフェメラルなものを分ける。
- Permanent page(
permanent: true): 不変の URL で公開したいもの - Note page(
permanent: false): 個人的なメモや下書き。noindex, nofollowで検索エンジンにもインデックスされず、いつでも消せる
note page はあくまで概念上の呼び名で、frontmatter に note: true のような専用フィールドがあるわけではない。コード上でも基本的には permanent === false として扱われる。
permanent は明示的に true と書かなくても、layout が page 以外だったり、特定のタグ(works, video 等)が付いていれば自動的に true に推定される(FrontmatterSchema の transform 参照)。