Penpotセルフホストの聖域:フォント管理の「闇」をコードで制圧する
Penpotはオープンソースのプロトタイピングツールとして極めて優秀だが、セルフホスト環境における「フォント管理」は、多くのチームが最初に直面する深淵だ。特に、マルチバイト文字を含むカスタムフォントをチーム全員のブラウザ環境で正確に同期させる際、単にファイルを配置するだけでは文字化けやレンダリング不一致の泥沼に足を取られる。
本稿では、Penpotの内部構造を理解した上で、Dockerベースの環境においてフォントを「コードとして管理」し、チーム全員に強制同期させるための極限の最適化手法を伝授する。
—
1. Penpotフォント管理の内部アーキテクチャを理解する
Penpotのアーキテクチャにおいて、フォントは単なるアセットではない。PenpotはクライアントサイドでのSVGレンダリングと、バックエンドでのエクスポート処理の双方でフォントを参照する。
Docker環境におけるフォントの適用は、以下の2つの層を同時に制圧する必要がある。
1. Frontend (Browser): ブラウザがCSS `@font-face` でフォントを読み込める状態にする。
2. Backend (Export Service): PDF/PNGエクスポート時にサーバーサイドでフォントを解決する。
ここを分離して考えると「なぜかプレビューは見えるがエクスポートで豆腐になる」という現象が起きる。これを解決するには、`penpot-backend` と `penpot-frontend` の双方に同一のフォントソースをマウントするのが唯一の正解だ。
—
2. 完全自動化構成:Docker Composeによるフォント注入
`docker-compose.yml` を拡張し、コンテナ起動時にホストOSのフォントディレクトリを強制的にマウントする構成がベストプラクティスだ。
services:
penpot-backend:
volumes:
# ホスト側のフォントリポジトリをコンテナ内の専用パスへ
- ./assets/fonts:/usr/share/fonts/custom:ro
environment:
# フォントパスを環境変数で明示的に指定
- PENPOT_FONT_PATH=/usr/share/fonts/custom
penpot-frontend:
volumes:
# 静的アセットとして配信するためのマウント
- ./assets/fonts:/app/static/fonts:ro
【極限の知見】パフォーマンスとメモリの最適化
フォントファイル(特にCJKフォント)は容量が大きい。Penpotのコンテナに数GBのフォントをマウントすると、起動時のインデックス生成でメモリを食いつぶす可能性がある。
- サブセット化の徹底: `pyftsubset` を使用し、デザインで使用するグリフのみを抽出したWoff2ファイルに軽量化せよ。
- CDNの検討: 規模が拡大した場合、Nginxコンテナを別途立てて、フォントのみCDN経由で配信させる設計へ移行せよ。
—
3. CLIで制御する:フォント同期自動化スクリプト
手動のファイルコピーは「環境の不整合」を招く最大の敵だ。Gitリポジトリにフォントを管理し、デプロイ時に同期させるシェルスクリプトをCI/CDパイプラインに組み込む。
!/bin/bash
sync_fonts.sh: チーム全員の環境でフォントを強制更新するスクリプト
set -e
FONT_DIR=”./assets/fonts”
TARGET_HOST=”penpot-server”
echo “>>> チーム共有フォントの最適化中…”
Woff2への変換と不要データの削除
for f in ./raw_fonts/.ttf; do
pyftsubset “$f” –output-file=”$FONT_DIR/$(basename “${f%.ttf}.woff2″)” \
–layout-features=” –flavor=woff2 –layout-features=”
done
echo “>>> コンテナへの同期完了”
docker cp $FONT_DIR penpot-backend:/usr/share/fonts/custom
docker restart penpot-backend
—
4. トラブルシューティング:文字化けとレンダリング崩れの正体
「ブラウザ上では表示されているのに、PDFにすると文字化けする」問題は、9割が `font-family` の名称不一致 に起因する。
原因の特定と解消
1. 名前の完全一致: `font-family` の内部名(PostScript名)と、CSSで指定する名前が一致しているか `fc-scan` コマンドで確認せよ。
2. Fontconfigのキャッシュ: Dockerコンテナ内で新しいフォントを追加した際、`fc-cache -fv` を実行しなければカーネルレベルで認識されない。
# コンテナ内で実行
docker exec -it penpot-backend fc-cache -fv
3. MIMEタイプの不備: NginxがWoff2を正しく配信しているかを確認する。設定ファイルに `application/font-woff2 woff2;` が漏れていると、ブラウザはフォントを無視する。
—
5. アーキテクトからの提言:デザインシステムとしての運用
フォントを単に「サーバーに入れる」だけでは不十分だ。チーム全員が同じフォントを使用することを強制するために、PenpotのAPIを活用した自動構成を推奨する。
PenpotのAPIを通じて、プロジェクトテンプレートにフォント設定をプリセットするスクリプトを走らせることで、「環境構築した瞬間に、全フォントが使用可能な状態」を実現できる。
結論:
Penpotをただのブラウザツールとして使うな。インフラからデザインまでの全レイヤーをコードで繋ぎ、環境差異という概念をこの世から抹消せよ。それこそが、伝説級のUIエンジニアが目指すべき「真の自動化」である。
君のチームのプロトタイピング環境が、今日から「完璧な同期」の領域に足を踏み入れることを期待している。