こんにちは!プロダクトデザイナーの先輩として、今日は君とちょっとワクワクする話をしよう。
「要件定義はNotion、デザインはPenpot。でも、仕様変更のたびにスクリーンショットを撮ってNotionに貼り直すのがダルい……」「ステークホルダーから『最新のデザインどこだっけ?』って毎日聞かれるのをどうにかしたい」
そんな絶望的なサイロ化(情報の孤立)に、今日で終止符を打とう。
今回は、オープンソースの最強デザインツール「Penpot」と、私たちの思考の母艦である「Notion」をAPIで完全結合させ、「デザインの変更が、自動でNotionのタスクボードに同期される神ワークフロー」の作り方を徹底解説するよ。
これをマスターすれば、非エンジニアのメンバーも常に最新のUIプレビューにアクセスできるようになり、無駄なSlackのやり取りが劇的に減る。さあ、一緒にセットアップしていこう!
—
1. ツールの役割:なぜ「Penpot × Notion」なのか?
まず、なぜこの組み合わせが最強なのかを整理しておこう。
- Penpotの役割:
SVGをネイティブ採用し、CSS GridやFlexboxの概念をそのままUIに落とし込める次世代のデザインツール。Figmaと違って完全にオープンソース(AGPLv3)だから、社内サーバーに立てることもできる。
- Notionの役割:
要件定義、仕様書、ロードマップ、そしてステークホルダー向けのダッシュボード。人間が読める言葉でプロダクトの文脈を統括する場所。
この2つをAPIで繋ぐ意義:
「デザイン」と「仕様」の乖離を防ぐこと。Penpotでアートボードが更新されたら、自動でそのサムネイルと更新日時がNotionのデータベースに飛ぶ。この仕組みを作れば、誰もが「今、何が作られているのか」の真実(Single Source of Truth)に迷わずアクセスできるようになるんだ。
—
2. 基礎セットアップ:APIの扉を開く
まずは、両方のツールで「会話するためのパスポート(APIトークン)」を発行しよう。
① Notion側の準備
1. [Notion Developers](https://www.developers.notion.com/) にアクセスし、新しいインテグレーション(Internal Integration)を作成する。
2. 機能を「Content capabilities(読み取り・書き込み)」に設定。
3. 発行された `Internal Integration Secret`(APIキー) をコピーしておく。
4. 同期先のNotionデータベース(例:「デザイン進捗管理ボード」)を開き、右上の「…」から「接続する(Add connections)」で、今作ったインテグレーションを追加する。
② Penpot側の準備
Penpotはセルフホスト版か公式クラウド版(penpot.app)のどちらでもOK。
Penpot自体にはまだ公式のWebhook機能が全機能に網羅されていないため、今回は「PenpotのAPI / エクスポート機能」と、両者を繋ぐグルーヴ(自動化スクリプト)として「Node.js + GitHub Actions(またはローカル環境)」を使うよ。
—
3. HelloWorld的動作確認:最小限のスクリプトで同期をテストする
百聞は一見にしかず。まずは「Penpotのアートボード情報を取得し、Notionのデータベースに1件のページを作る」という最小限のスクリプト(HelloWorld)を書いてみよう。
プロジェクトフォルダを作り、以下のコードを `sync.js` として保存してほしい。
// sync.js
// Penpotのデータを取得し、Notionに流し込む最小限のスクリプト
const NOTION_API_KEY = ‘secret_あなたのNotionインテグレーションキー’;
const DATABASE_ID = ‘あなたのNotionデータベースID’;
async function testConnection() {
console.log(‘🚀 Notionへのデータ送信テストを開始します…’);
const response = await fetch(‘https://api.notion.com/v1/pages’, {
method: ‘POST’,
headers: {
‘Authorization’: `Bearer ${NOTION_API_KEY}`,
‘Notion-Version’: ‘2022-06-28’,
‘Content-Type’: ‘application/json’,
},
body: JSON.stringify({
parent: { database_id: DATABASE_ID },
properties: {
// Notion側のデータベースにある「名前」プロパティに対応
“タスク名”: {
title: [
{
text: {
content: “【HelloWorld】Penpot連携テスト”,
},
},
],
},
// 「ステータス」プロパティに対応
“ステータス”: {
status: {
name: “進行中”,
},
},
},
}),
});
if (response.ok) {
console.log(‘✨ 大成功!Notionのデータベースを確認してください。新しい行が追加されています。’);
} else {
const errorData = await response.json();
console.error(‘❌ エラーが発生しました:’, errorData);
}
}
testConnection();
これをターミナルで実行してみよう。
node sync.js
どうだい?Notionのデータベースに「【HelloWorld】Penpot連携テスト」という行がスッと追加されたはずだ。これが、すべての自動化の土台となる。
—
4. 実戦投入:デザイン変更を自動でNotionに同期する裏技
ここからが本番だ。Penpotでデザインを修正した際、そのアートボードを画像として書き出し、Notionのタスクカードの「カバー画像」や「プロパティ」に自動反映させる完全版のワークフローを構築しよう。
今回は、手軽かつ堅牢に動かすために、GitHub Actionsを使って「毎日深夜」または「手動トリガー(workflow_dispatch)」で同期する仕組みを作る。
1. 設定ファイル(`.github/workflows/penpot-sync.yml`)の作成
GitHubリポジトリの `.github/workflows/` ディレクトリに以下のファイルを作成する。
name: Penpot to Notion Sync
on:
workflow_dispatch: # GitHubの画面から手動で実行できるようにする
jobs:
sync:
# 環境を構築
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: ’18’
- name: Install dependencies
run: npm install node-fetch
- name: Run Sync Script
env:
NOTION_API_KEY: ${{ secrets.NOTION_API_KEY }}
NOTION_DATABASE_ID: ${{ secrets.NOTION_DATABASE_ID }}
PENPOT_API_TOKEN: ${{ secrets.PENPOT_API_TOKEN }}
PENPOT_FILE_ID: ${{ secrets.PENPOT_FILE_ID }}
run: node scripts/sync-design.js
2. 同期スクリプトの本番実装(`scripts/sync-design.js`)
PenpotのAPIを叩いてファイル情報を取得し、Notion側のステータスを更新するスクリプトの全貌がこれだ。
// scripts/sync-design.js
const NOTION_API_KEY = process.env.NOTION_API_KEY;
const DATABASE_ID = process.env.NOTION_DATABASE_ID;
const PENPOT_API_TOKEN = process.env.PENPOT_API_TOKEN;
const PENPOT_FILE_ID = process.env.PENPOT_FILE_ID;
// ※実運用ではPenpotのファイル構造に合わせてエンドポイントやデータをパースします
async function syncPenpotToNotion() {
console.log(‘🎨 Penpotから最新のデザイン情報を取得中…’);
// 1. Penpot APIからファイルデータを取得 (エンドポイントは環境に合わせて調整)
// 公式クラウドまたはセルフホストのAPI仕様に基づきます
/
const penpotRes = await fetch(`https://design.penpot.app/api/files/${PENPOT_FILE_ID}`, {
headers: { ‘Authorization’: `Bearer ${PENPOT_API_TOKEN}` }
});
const fileData = await penpotRes.json();
/
// ここではモックとして、アートボード名「ログイン画面 v2」が更新されたと仮定
const updatedArtboards = [
{ name: “ログイン画面 v2”, status: “レビュー待ち”, updated: new Date().toISOString() }
];
for (const board of updatedArtboards) {
console.log(`📝 Notionを更新中: ${board.name}`);
await fetch(‘https://api.notion.com/v1/pages’, {
method: ‘POST’,
headers: {
‘Authorization’: `Bearer ${NOTION_API_KEY}`,
‘Notion-Version’: ‘2022-06-28’,
‘Content-Type’: ‘application/json’,
},
body: JSON.stringify({
parent: { database_id: DATABASE_ID },
properties: {
“タスク名”: {
title: [{ text: { content: board.name } }]
},
“ステータス”: {
status: { name: board.status }
},
“最終更新”: {
date: { start: board.updated }
}
}
})
});
}
console.log(‘🎉 すべての同期が完了しました!’);
}
syncPenpotToNotion();
GitHubのRepository SecretsにそれぞれのAPIキーを設定しておけば、ボタンをポチるだけでPenpotのデザイン進捗がNotionに美しく集約される。
—
おわりに:チームの共通言語をデザインしよう
いかがだっただろうか?
今回はあえてプログラ営的なアプローチ(APIとスクリプト)を交えて、PenpotとNotionをシームレスに繋ぐ方法を解説した。
「デザインはデザインツールの中だけ」「タスクはタスク管理ツールの中だけ」という古い壁を壊し、「要件定義からデザイン進捗までがひとつの文脈として繋がっている状態」を作ること。それこそが、優れたUI/UXエンジニアやプロダクトデザイナーが目指すべき環境構築の醍醐味だ。
これを導入すれば、明日からのチームの会話はこう変わるはずだ。
「あ、新しいデザインの反映、Notionのボード見れば一発でわかりますよ!」
これをマスターすれば、毎日の作業が劇的に楽になりますよ。ぜひ、あなたのプロジェクトでも試してみてほしい。感想や「もっとこうしたい」というカスタマイズの相談があれば、いつでも声をかけてくれよな!