アーキテクチャ
NotroTail がどのように動作するか、システム全体の設計と各コンポーネントの役割を解説します。
パッケージ構成
npm ワークスペースモノレポで3つのパッケージを管理しています。
| パッケージ | パス | 役割 |
|---|---|---|
remark-nfm | packages/remark-nfm/ | Notion Flavored Markdown 向け純粋 remark プラグイン。Astro 依存なし。 |
notro | packages/notro/ | 公開 npm ライブラリ。Astro Content Loader・MDX コンパイル・Notion ブロックコンポーネント。 |
notro-tail | apps/notro-tail/ | デプロイ可能な Astro 6 ウェブサイト(テンプレート実装)。 |
3種類のページ
| 種類 | URL 例 | コンテンツソース | ブログ一覧表示 |
|---|---|---|---|
| 静的ページ | /, /docs/ | src/pages/ 内の .astro ファイル | なし |
| 埋め込みページ | /blog/about/ | Notion データベース — page タグ付き | 非表示(タグフィルターで除外) |
| ブログ記事 | /blog/my-post/ | Notion データベース — page タグなし | 表示 |
コンテンツローディングフロー
- 1
Astro Content Collections の定義
content.config.tsでpostsコレクションを定義し、loader()を設定。 - 2
Notion Public API からのデータ取得
loader()がdataSources.queryでページ一覧を取得し、pages.retrieveMarkdownで Markdown を取得。last_edited_timeでキャッシュし、変更ページのみ再取得。 - 3
前処理済み Markdown をストアに保存
preprocessNotionMarkdown()で Notion Markdown の構造的な問題を修正し、 Astro Content Collection ストアに保存。 - 4
レンダリング時の MDX コンパイル
NotroContentがcompileMdxCached()で@mdx-js/mdxのevaluate()を呼び出し、<Content components={notionComponents} />でレンダリング。 - 5
Notion ブロックコンポーネントへのマッピング
コールアウト・トグル・カラム・数式(KaTeX)・目次など、各 Notion ブロックタイプが
src/components/notion/の Astro コンポーネントにマッピングされる。
MDX コンパイルパイプライン
packages/notro/src/utils/compile-mdx.ts
内で定義。astro.config.mjs の設定は不要で、
レンダリング時に NotroContent 内で実行されます。
Remark プラグイン(Markdown → mdast)
remarkNfm— 前処理・ディレクティブ・コールアウト変換をまとめて実行remark-gfm— GitHub Flavored Markdown(テーブル・取り消し線等)remark-math— インライン・ブロック数式構文
Rehype プラグイン(hast → HTML)
rehypeKatex— 数式ノードを KaTeX HTML にレンダリングresolvePageLinksPlugin— Notion 内部リンクをlinkToPagesマップで解決@shikijs/rehype— コードブロックのシンタックスハイライト
画像ハンドリング
apps/notro-tail/src/lib/notionImageService.ts
は Astro の Sharp 画像サービスをラップし、Notion S3 プリサイン URL から
X-Amz-*
クエリパラメーターを除去してキャッシュキーを計算します。
これにより、同じ画像の URL が期限切れで変わっても、ビルドキャッシュが再利用されます。