【テクニカル・上級編】PenpotとStorybookの連携ワークフロー:デザインシステムをコンポーネント単位で双方向同期する実践ガイド – UI/UX・デザインツール活用バイブル

Penpot × Storybook:デザインシステムを「コードの真実」へと昇華させる自動化アーキテクチャ

多くのチームが「デザインとコードの乖離」という亡霊に追われている。Figmaで描かれた美しいレイヤー構造は、エンジニアの手元に届く頃には形骸化し、Storybookはただの「静的なカタログ」と化す。

だが、オープンソースの旗手である Penpot と Storybook を組み合わせるなら、その状況は一変する。両者は単なるツールではなく、「単一の情報源(SSOT)」を構築するための強力なプリミティブだ。

本稿では、PenpotのFlex Layoutの意図をStorybookのPropsへ直接注入し、CI/CDパイプライン上でデザイン更新を検知してコンポーネントを再生成する「フルスタック・同期アーキテクチャ」の核心を解説する。

—

1. デザインシステムの設計思想:CSS Grid/Flexの「型」を共有する

PenpotがFigmaと決定的に異なるのは、その内部構造がWeb標準のCSS GridとFlexboxに極めて近いことだ。この「Webネイティブな構造」こそが、自動化の鍵となる。

構築の鉄則:デザイン・トークンの抽象化

UIコンポーネントを直接同期しようとしてはいけない。まずは、「Design Token(JSON)」を仲介させるレイヤーを構築する。

1. PenpotのStyles: 色、タイポグラフィ、スペーシングをPenpot側でCSS変数名と一致させる。
2. Penpot API: `GET /api/rpc/get-file` を叩き、デザイン上の定義を抽出する。
3. Style Dictionary: 抽出したJSONを、`tokens.json`として配布し、Tailwind CSSやCSS Variablesへ変換する。

—

2. APIを用いた「同期パイプライン」の構築

PenpotのAPIは、単なるメタデータ以上の情報を吐き出す。これを利用し、Penpot上のコンポーネント定義からStorybookの `argTypes` を自動生成するスクリプトを組む。

自動生成スクリプト(Node.js/TypeScript)

以下は、Penpotのコンポーネント定義をStorybookのメタデータに変換するハックのプロトタイプだ。

// scripts/sync-penpot-to-storybook.ts
import { PenpotClient } from ‘@penpot/api’;

/

  • Penpotからコンポーネントの構造を抽出し、Storybook用のメタデータを生成する
  • 内部的にはPenpotのFlexプロパティをCSS属性のPropsとしてマッピングする

/
async function generateComponentMetadata(componentId: string) {
const client = new PenpotClient({ token: process.env.PENPOT_API_TOKEN });
const component = await client.getComponent(componentId);

// コンポーネントのプロパティをCSS Variableへ変換するロジック
const argTypes = component.properties.reduce((acc, prop) => {
acc[prop.name] = {
control: prop.type === ‘color’ ? ‘color’ : ‘text’,
description: `Synced from Penpot: ${prop.id}`,
};
return acc;
}, {});

return `
export const argTypes = ${JSON.stringify(argTypes, null, 2)};
`;
}

このスクリプトを `husky` や `GitHub Actions` のワークフローに組み込めば、デザイナーがPenpotでコンポーネントのPropsを増やした瞬間に、エンジニアのStorybookへ変更が即座に反映される「コントラクト・ファースト」な環境が整う。

—

3. パフォーマンスと最適化のハック

数千のコンポーネントを管理する場合、APIの呼び出し頻度はボトルネックとなる。ここで「差分検知(Diffing)」による最適化を行う必要がある。

内部アーキテクチャの最適化:ハッシュ値によるキャッシュ

PenpotのSVG出力やJSONメタデータには、変更されるたびに変化する `revisionId` が含まれる。これをローカルの `.penpot-cache` に保存し、ハッシュが一致する場合のみ再生成を行う。

簡易的な同期フロー
penpot-cli sync –project-id=XYZ –cache-dir=.penpot-cache –force-update=false

これにより、ビルドパイプラインのメモリ消費を抑えつつ、CIの実行時間を数秒単位まで短縮できる。

—

4. なぜ「双方向」を目指すのか

多くの開発者は「デザイン→コード」の一方通行しか考えないが、真の熟練者は「コード→デザイン」へのフィードバックループを設計する。

1. Storybook CLIでの変更検知: Storybookのストーリーが書き換わった際に、Penpot APIを通じて「デザイン側のドキュメントを更新する」または「警告を飛ばす」仕組みを実装する。
2. デザインの型安全: Storybookの `controls` が、Penpotのデザイン仕様とズレた場合に、CI上でエラーを投げる。これにより、エンジニアの独断によるスタイル変更を「視覚的な規約違反」として即座に検知する。

—

結論:ツールを「支配」せよ

PenpotとStorybookの連携は、単なる業務効率化ではない。これは「UIの定義をコードとして宣言し、デザインをその実装へと同期させる」という、フロントエンド・アーキテクチャの究極系だ。

自動化スクリプトは、ツールに振り回されるためのものではない。ツールが持つAPIを骨の髄まで掌握し、自分たちの開発プロセスに合わせて「再定義」するための道具だ。

今日から、コンポーネント一つひとつのメタデータをコードベースに移植し、デザインシステムという名の「生きた真実」をGitの履歴に刻み込むのだ。それが、UIエンジニアが到達すべき最高地点である。

タイトルとURLをコピーしました