Notion を CMS として、Astro (Vue) で静的ビルドし Cloudflare Pages にデプロイする短文ブログ。
- Notion ブロック構造をそのままレンダリング — Markdown 変換を挟まず、Notion API のブロックデータを Vue コンポーネントで再帰的に描画する
- ビルド時に外部リソースをローカル化 — bookmark / link_preview の OGP 取得、Notion 画像と OGP 画像のダウンロード (src/lib/enrichBlocks.ts)
- oEmbed エンドポイント — 各記事の埋め込みメタデータを
/oembed/<id>.jsonで配信 - 自動ビルドトリガー — Notion DB の変更を検知して Cloudflare Pages のビルドを叩く Cloudflare Worker を同梱 (worker/)
- Notion Integrations にアクセス
- 「新しいインテグレーション」を作成し、Internal Integration Token を控える
- 作成したインテグレーションに コンテンツの読み取り 権限があることを確認
ブログ記事を管理するデータベースを作成し、以下のプロパティを設定する:
| プロパティ名 | タイプ | 説明 |
|---|---|---|
| Title | Title | 記事タイトル |
| Published | Checkbox | 公開フラグ |
| First published at | Date | 公開日 (一覧のソートキー) |
Last edited time は Notion が自動付与するため設定不要。
データベース ID は URL から取得:
https://www.notion.so/<workspace>/<DATABASE_ID>?v=...
^^^^^^^^^^^^
npm install
# .env を作成
cp .env.example .env
# NOTION_TOKEN と NOTION_DATABASE_ID を設定npm run devnpm run build
npm run previewサイト情報は環境変数で上書きできる (astro.config.mjs)。
| 環境変数 | デフォルト値 | 用途 |
|---|---|---|
SITE_NAME |
note |
サイト名 |
SITE_DESCRIPTION |
Notionをブログのように公開するためのサイト |
サイト説明文 |
SITE_AUTHOR |
author |
著者名 (フッター / oEmbed の author_name) |
SITE_COPYRIGHT_YEAR |
ビルド実行年 | フッターの著作権表示年 |
SITE_URL |
https://your-blog.pages.dev |
公開ドメイン (canonical URL / OGP / oEmbed の URL に使用) |
- リポジトリを GitHub に push
- Cloudflare Dashboard → Pages → 「プロジェクトを作成」
- Git リポジトリを接続
- ビルド設定:
- フレームワークプリセット: Astro
- ビルドコマンド:
npm run build - ビルド出力ディレクトリ:
dist
- 環境変数に
NOTION_TOKEN/NOTION_DATABASE_IDを設定 - デプロイ
worker/ 以下に Cloudflare Worker を同梱している。Cron Trigger (デフォルト 5 分間隔) で Notion DB を覗き、ページ集合か last_edited_time に差分があれば Pages の Deploy Hook を叩いてビルドを起動する。
詳細は worker/README.md を参照。
note/
├── astro.config.mjs # Astro 設定 (Vue 統合 / env スキーマ)
├── public/
│ ├── favicon.svg # ロゴ兼ファビコン
│ └── ogp/ # ビルド時にダウンロードした OGP 画像置き場
├── src/
│ ├── site.ts # 環境変数からサイト情報を再エクスポート
│ ├── lib/
│ │ ├── notion.ts # Notion API クライアント (一覧/ページ/ブロック取得)
│ │ ├── enrichBlocks.ts # bookmark/link_preview の OGP 取得 + 画像ダウンロード
│ │ └── ogp.ts # OGP メタデータ取得・画像処理 (cheerio + sharp)
│ ├── components/
│ │ ├── NotionRenderer.vue # ブロックレンダラー (再帰)
│ │ ├── RichText.vue # リッチテキストレンダラー
│ │ ├── SiteHeader.astro # サイト共通ヘッダー
│ │ ├── PostHeader.astro # 記事メタ表示
│ │ └── blocks/ # ブロック種別ごとのコンポーネント
│ ├── layouts/
│ │ └── Base.astro # 共通レイアウト (head / OGP / oEmbed link)
│ ├── pages/
│ │ ├── [...page].astro # 記事一覧 (10 件ごとページネーション)
│ │ ├── posts/[id].astro # 記事詳細 (Notion page id をそのまま URL に使用)
│ │ └── oembed/[id].json.ts # oEmbed エンドポイント
│ └── styles/
│ └── global.css # グローバルスタイル (Bootstrap 5.3 ベース)
└── worker/ # 自動ビルドトリガー用 Cloudflare Worker
MIT