PenpotとNotionの双方向連携ワークフロー:要件定義からデザイン進捗管理を一元化する裏技
テックリードやシニアデザイナーの仕事は、美しい画面を作ることではない。「プロダクトの意図(Intent)と実装(Implementation)、そしてビジネスの要件(Requirements)を完璧に同期させ、チームの認知負荷を最小化すること」だ。
Figma全盛の現在、オープンソースであり、セルフホスト可能、かつSVGネイティブなDOM構造を持つ「Penpot」に注目しているチームは、感度が高い。しかし、どんなに優れたデザインツールを使っても、「要件定義はNotion、デザインはPenpot、進捗管理はJira/GitHub」とサイロ化(縦割り)していては、ステークホルダーとのコンテキストの剥離(Context Drift)を防げない。
今回は、PenpotとNotionをシームレスに結合し、要件定義からデザインの変更履歴、ステークホルダーへの共有までを一元化する「プロフェッショナル・ワークフロー」の極意を伝授しよう。退屈なマニュアルではない。現場の生産性を暴力的に引き上げる実践知をここに公開する。
—
1. 思想:なぜPenpot × Notionなのか?
Figmaのプラグインエコシステムは強力だが、クローズドなSaaSの壁がある。一方、Penpotはオープンソースであり、そのファイル構造の実態はSVGとJSONの塊だ。つまり、データの主権がこちら側にある。
Notionを「プロダクトの唯一の真実の源(Single Source of Truth: SSOT)」とし、Penpotを「ビジュアルなプレースホルダー」として機能させる。この2つをAPIで架橋することで、PM、エンジニア、デザイナーの間で「今どの画面がどの要件に紐づいていて、どのステータスにあるのか」の共通認識を1秒のズレもなく同期できる。
—
2. 現場のスピードを爆上げする:Penpotの隠れたキル技
まずは、デザインの筆速を極限まで高めるためのキーボードショートカットと設定だ。これらをチーム全員に強制することから、プロジェクトは始まる。
開発スピードを加速するキーボードショートカット
- `Shift + R`:CSS Gridのトグル(Penpotの真骨頂であるCSS Gridを即座に呼び出し、レスポンシブなコンポーネント構造を強制する)
- `Alt + Drag`:正確なパディング測定とコンポーネントの派生作成
- `Ctrl/Cmd + Shift + F`:コンポーネントのアタッチ・デタッチの切り替え
- `V`(移動)と `A`(アートボード)の素早いコンテキストスイッチ
チーム開発で絶対に統一すべき「コンポーネント命名規則」
Notionとの自動同期を行う前提として、Penpot側のレイヤー構造が汚染されていてはスクリプトが崩壊する。以下のBEM(Block Element Modifier)ライクな命名規則をチーム規約として定着させよ。
> `[Component] / [State] / [Property]`
> 例: `Btn / Primary / Hover`
—
3. 実装:PenpotとNotionを自動同期するパイプラインの構築
ここからが本題だ。PenpotのWebhook、あるいは定期実行のGitHub Actions / Node.jsスクリプトを用いて、Penpotのアートボード変更をNotionデータベースに自動反映するパイプラインを構築する。
ステークホルダー(非エンジニア)はNotionのボードビューを見るだけで、最新のデザインプレビューと要件の進捗を確認できる状態を作る。
ステップ1: データの受け渡しを定義する JSONスキーマ
Penpotのエクスポートデータ、またはWebhookから飛んでくるペイロードを解釈し、Notionのページプロパティにマッピングするための設定ファイル(`config.json`)のベストプラクティスだ。
{
“$schema”: “http://json-schema.org/draft-07/schema#”,
“title”: “PenpotNotionSyncConfig”,
“type”: “object”,
“properties”: {
“workspaceId”: {
“type”: “string”,
“description”: “PenpotのターゲットワークスペースID”
},
“fileId”: {
“type”: “string”,
“description”: “同期対象のPenpotファイルID”
},
“notionDatabaseId”: {
“type”: “string”,
“description”: “連携先のNotionデータベースID”
},
“mappingRules”: {
“type”: “array”,
“items”: {
“type”: “object”,
“properties”: {
“penpotArtboardRegex”: {
“type”: “string”,
“description”: “同期対象を絞り込むためのアートボード名の正規表現”
},
“notionStatus”: {
“type”: “string”,
“description”: “Notion側で設定する初期ステータス(例: ‘Reviewing’, ‘Ready for Dev’)”
}
},
“required”: [“penpotArtboardRegex”, “notionStatus”]
}
}
},
“required”: [“workspaceId”, “fileId”, “notionDatabaseId”, “mappingRules”]
}
ステップ2: 同期を自動化するスクリプト(Node.js / TypeScript Snippet)
実際のプロジェクトで組み込む際の、Notion APIとPenpot API(またはSVGプレビュー生成部)を繋ぐコアロジックの断片だ。これをCI/CDパイプラインや定期実行サーバー(AWS Lambda / Vercel Cron等)に組み込む。
import { Client } from “@notionhq/client”;
import axios from “axios”;
import as dotenv from “dotenv”;
dotenv.config();
// Notionクライアントの初期化
const notion = new Notion({ auth: process.env.NOTION_API_KEY });
const DATABASE_ID = process.env.NOTION_DATABASE_ID;
const PENPOT_API_URL = process.env.PENPOT_API_URL; // セルフホスト環境のURL
const PENPOT_TOKEN = process.env.PENPOT_ACCESS_TOKEN;
interface ArtboardSyncPayload {
name: string;
previewUrl: string;
lastModified: string;
}
async function syncArtboardsToNotion(artboards: ArtboardSyncPayload[]) {
for (const board of artboards) {
try {
// Notionデータベースから既存ページを検索(アートボード名で一意に特定)
const existingPage = await notion.databases.query({
database_id: DATABASE_ID!,
filter: {
property: “Screen Name”,
title: {
equals: board.name,
},
},
});
if (existingPage.results.length > 0) {
// 既存ページがある場合はプレビューと更新日時をアップデート
const pageId = existingPage.results[0].id;
await notion.pages.update({
page_id: pageId,
properties: {
“Last Synced”: {
date: { start: new Date().toISOString() },
},
“Preview”: {
url: board.previewUrl,
},
},
});
console.log(`[Updated] Notion page for: ${board.name}`);
} else {
// 新規ページの場合はデータベースに追加
await notion.pages.create({
parent: { database_id: DATABASE_ID! },
properties: {
“Screen Name”: {
title: [
{
text: { content: board.name },
},
],
},
“Status”: {
status: { name: “Needs Review” },
},
“Preview”: {
url: board.previewUrl,
},
},
});
console.log(`[Created] Notion page for: ${board.name}`);
}
} catch (error) {
console.error(`Failed to sync artboard ${board.name}:`, error);
}
}
}
// 実行モック
// 実際にはPenpotのWebhookトリガーやファイル変更検知フックから呼び出す
—
4. チーム運用におけるガバナンスと設定共有ルール
ツール間の連携を自動化しても、運用ルールが崩壊すれば意味がない。テックリードとしてチームに強制すべき「3つの鉄則」を挙げる。
1. 「Notionが親、Penpotが子」の原則を崩さない
- 機能要件の変更、アクセシビリティの注記、APIの仕様は必ずNotion側を先行して更新する。デザインの変更は、Notionの要件ID(例: `REQ-042`)をPenpotのアートボードのメモまたは名前に含めること。
2. ステークホルダーにはNotionの「ギャラリービュー」を強制配付する
- 非エンジニアやPdMには、Penpotの複雑な編集画面を触らせない。Notion上に自動生成されたギャラリービュー(プレビュー画像付き)を見せることで、「今どの画面がどうなっているか」の共通認識を保つ。
3. 変更履歴のトレーサビリティ
- PenpotのSVG出力構造とGitを連携させ、デザインのコミットログをコード側でも追えるようにバックアップ体制を構築する(Penpotのバックアップファイルを定期的にS3等へdumpするCronを走らせる)。
—
5. まとめ:ツールに踊らされず、システムをハックせよ
多くのチームは、「どのデザインツールを使うか」で議論に時間を溶かす。しかし、本当に重要なのは「アイデア(要件)が、どのように画面(デザイン)になり、それがどうコード(実装)に落ちて、最終的にどこで進捗管理されるか」という情報の流通経路(パイプライン)の設計である。
Penpotのオープン性とNotionの柔軟性をAPIで結合したこのワークフローは、単なる「便利ツール連携」ではない。チーム全体の認知の摩擦をゼロにし、プロダクト開発のベロシティを極限まで高めるための「エンジニアリング・デザイン手法」なのだ。
今日からあなたのプロジェクトでも、このパイプラインを構築し、無駄なミーティングとコンテキストのズレを根絶してほしい。