Gemini アプリで @Canva と打ったときに、自分の Canva ワークスペース側の Brand Kit が「ちゃんと見えている」状態でデザインが返ってきた瞬間、これは AI アシスタントとデザインツールの距離がはっきり縮まったと感じました。アート活動と並行して dolice.design でクリエイティブ制作も請けており、毎週 SNS 投稿用のビジュアルを 20 〜 30 点ほど回しています。1 週間この連携を運用してみた所感を、設計者と実装者の両方の視点で残します。
PRONEWS の公式発表記事「Canva が Google Gemini 内でデザイン生成が可能に。チャットから直接レイアウト作成や編集を実行 」が伝えているとおり、Canva の MCP(Model Context Protocol)サーバーを搭載した AI コネクタが Gemini アプリ内で直接動作するようになりました。Claude、ChatGPT、Microsoft Copilot に続く流れですが、Gemini との連携は Workspace の各サービスや Google フォトと地続きで動かせる点で、独立した意味を持ちます。今日はそこを具体的な運用に翻訳します。
なぜ「会話のすぐ隣にデザイン」が効くのか
Canva は以前から完成度の高いエディタを持っていましたが、個人事業者にとって一番の摩擦は 「画面を切り替えるたびに意図が痩せる」 ことでした。Gemini で投稿のアイデアを練り、別タブで Canva を開き、Brand Kit を確認しながらテンプレートを探すうちに、最初に頭にあった像が薄れていく。チャットの履歴を遡って思い出すたびに、3 〜 4 分ずつ手が止まります。
@Canva を Gemini 内から呼べるようになると、この摩擦が消えます。ただ「消えた気がする」で終わらせると、来月には同じ議論をもう一度することになります。後半で作業ログから工程別に測り直しますので、まずは運用側の設計から書きます。
接続:認可とアカウント分離で最初に押さえる 4 点
接続自体は驚くほど簡単で、Gemini 側で @Canva と打ち、ワンタップで Canva アカウントの認可フローに飛びます。ただ、本番運用に乗せる前に押さえるべき点がいくつかありました。
第 1 に、認可スコープです。Canva は「自分のデザインを参照・編集する権限」を Gemini に渡しますが、Canva Pro / Enterprise のチーム機能を使っている場合、共有テンプレートにどこまで触れるかは Canva 側のロール設定が優先されます。私の場合は dolice.design の個人アカウントと、外部クライアント案件用のアカウントを分けており、Gemini からは個人アカウントだけを接続する形にしました。複数アカウントを束ねたい誘惑がありますが、Brand Kit の意図しない流用が起きやすくなるので避けています。
第 2 に、プライバシー設計です。Gemini と Canva のあいだはプライベートかつ安全に同期される、と公式は説明していますが、Gemini に送られたプロンプト本文と、生成結果として @Canva が返したデザインのメタデータは、Gemini 側の履歴にも残ります。社外秘のキャンペーン情報をプロンプトに書く運用は避け、私は「タイトル」「想定媒体」「ブランドカラー名」までに留めています。
第 3 に、応答時間の体感値です。1 週間で 80 リクエストほど投げましたが、生成や検索のレスポンスは数秒〜十数秒の範囲に収まり、Canva エディタを単独で開くのと比べてストレスを感じる場面はほぼありませんでした。
第 4 に、誤起動防止です。Gemini のチャット中に @Canva が文脈で自動補完されると、意図しないデザイン生成が走ることがあります。設定で @ 補完の挙動を確認し、私は普段の会話セッションと、デザイン制作セッションを別ウィンドウに分ける運用に落ち着きました。
Brand Kit を「最初のプロンプト」から効かせる書き方
この連携の魅力は、最初のプロンプトから Brand Kit を効かせられることだと感じています。具体例で書きます。
dolice.design 用の Instagram キャリア投稿を作るときの、Gemini への 1 投目はこうです。
@Canva 私の Brand Kit 「dolice-design-2026」を参照して、Instagram 縦長 (1080×1350) のキャリア投稿の表紙を作って。タイトルは「光の輪と認知世界 ― 視覚表現の起点」。サブタイトルに「dolice.design 2026 Spring」。ブランドフォントの見出しと、ブランドカラーのプライマリを背景に、サブはオフホワイト。
返ってきたデザインは、ロゴカラーとフォントが期待通りに乗っていました。これまでテンプレを呼び出して手動で色とフォントを差し替えていた工程が、ほぼ 1 ターンで終わります。Brand Kit に登録した色名(「primary」「ink-black」など)を直接プロンプトで参照できるのも、後続の微調整(「サブタイトルを ink-black に」)が言葉だけで通る理由になっています。
注意点は、Brand Kit の名前を曖昧にしないことです。「ブランドカラー」「うちの色」のような指示だと、Gemini 側が推測で別の色を当てることがありました。Brand Kit 名と色名を必ず入れるルールにしてから、生成 1 発目の歩留まりが体感で 6 割から 9 割に上がっています。
あわせて、公式アナウンスにあった Canva Enterprise 向けの「会話の文脈からブランドテンプレートを自動入力する」機能も気になっていました。Enterprise 契約ではありませんが、Canva 側に「キャリア投稿テンプレ v3」「展示告知テンプレ v2」のような名前付きテンプレを 5 〜 10 本用意し、プロンプトに「テンプレ『キャリア投稿テンプレ v3』を流用して、内容だけ差し替えて」と書く運用で近いところまでは寄せられました。正規機能が個人 Pro に降りてくるかは未確定ですが、テンプレを命名規則で揃えておけば、降りてきた日にそのまま乗り換えられます。
指定漏れを人間の注意力に預けない — プロンプトを生成器から組み立てる
ルールを決めても、忙しい日は必ず書き忘れます。実際、金曜の夕方に投げた 3 件は Brand Kit 名を落としており、返ってきた背景色が 1 トーン外れていました。「気をつける」で解決しない類の失敗なので、プロンプトを手で書くのをやめ、小さな生成器を挟むことにしました。
やることは 2 つだけです。未定義の色名を組み立て段階で落とすことと、媒体ごとの安全領域を必ず末尾に付けることです。
# tools/canva_prompt.py — Brand Kit 指定と安全領域を機械的に埋める
import json, sys
MEDIA = {
# key: (幅, 高さ, 可読領域から外す上下の割合, ロゴ位置)
"ig_post" : ( 1080 , 1350 , 0.08 , "右下 80px 角" ),
"ig_story" : ( 1080 , 1920 , 0.12 , "中央下 96px 角" ),
"threads" : ( 1080 , 1350 , 0.08 , "右下 80px 角" ),
"x_header" : ( 1500 , 500 , 0.20 , "左下 64px 角" ),
"note_cover" : ( 1280 , 670 , 0.10 , "右下 72px 角" ),
}
def load_kit (path = "brand_kit.json" ):
kit = json.load( open (path, encoding = "utf-8" ))
for key in ( "name" , "colors" , "fonts" ):
if key not in kit:
raise ValueError ( f "brand_kit.json に { key } がありません" )
return kit
def color_ref (kit, name):
"""色名を必ず『名前 (#HEX)』に展開する。未定義ならここで落とす。"""
if name not in kit[ "colors" ]:
known = ", " .join( sorted (kit[ "colors" ]))
raise KeyError ( f "未定義の色名: { name } (定義済み: { known } )" )
return f ' { name } ( { kit[ "colors" ][name] } )'
def build (kit, media_key, title, subtitle, bg, fg):
if media_key not in MEDIA :
raise KeyError ( f "未定義の媒体: { media_key } " )
w, h, margin, logo = MEDIA [media_key]
return (
f '@Canva Brand Kit 「 { kit[ "name" ] } 」を参照して、 { w } × { h } の表紙を作ってください。 \n '
f 'タイトル「 { title } 」/ サブタイトル「 { subtitle } 」。 \n '
f '見出しフォントは { kit[ "fonts" ][ "heading" ] } 、'
f '背景は { color_ref(kit, bg) } 、文字は { color_ref(kit, fg) } 。 \n '
f '可読領域は上下 { int (margin * 100 ) } % を外し、ロゴは { logo } に固定してください。'
)
if __name__ == "__main__" :
kit = load_kit()
print (build(kit, sys.argv[ 1 ], sys.argv[ 2 ], sys.argv[ 3 ],
bg = sys.argv[ 4 ], fg = sys.argv[ 5 ]))
brand_kit.json 側はこれだけです。
{
"name" : "dolice-design-2026" ,
"colors" : {
"primary" : "#1B2A4A" ,
"accent" : "#E0553B" ,
"ink-black" : "#14161A" ,
"off-white" : "#F4F1EA"
},
"fonts" : { "heading" : "Zen Old Mincho" , "body" : "Noto Sans JP" }
}
color_ref() が KeyError を投げる設計にしたのが、この小道具の要点です。以前は「サブはオフホワイトで」と日本語で書いており、Brand Kit に off-white として登録してある事実と、プロンプト上の「オフホワイト」が別物であることに気づいていませんでした。名前を辞書のキーとして扱うと、その齟齬がターミナルで止まります。生成を 1 回投げてから目で気づくより、はるかに安いところで止まってくれます。
媒体定義を MEDIA に閉じ込めたのも意図があります。安全領域は媒体側の都合で変わるため、思い出しながら書くと媒体ごとにブレます。表にして 1 か所に置くと、後述の書き出しチェックとも同じ数字を共有できます。
媒体 サイズ 可読領域から外す帯 ロゴ位置
Instagram 投稿 1080×1350 上下 8% 右下 80px 角
Instagram ストーリーズ 1080×1920 上下 12% 中央下 96px 角
Threads 1080×1350 上下 8% 右下 80px 角
X ヘッダー 1500×500 上下 20% 左下 64px 角
note トップ画像 1280×670 上下 10% 右下 72px 角
X ヘッダーの 20% だけ極端に見えますが、プロフィール画像とボタンの重なりを避けると実際にこのくらい削ることになります。この数字を毎回思い出さずに済むようになってから、リサイズ後の手戻りが目に見えて減りました。
「マジックレイヤー」が変えた、生成 → 編集の境目
Gemini で生成した画像を @Canva 経由で Canva に持ち込むと、すべての要素が個別レイヤーに分解されて編集可能な状態になります。これが「マジックレイヤー」と呼ばれている機能で、私の運用ではこれが一番大きな変化でした。
これまでの AI 画像生成ツールでは、生成された 1 枚絵を Canva に持ち込むと、テクスチャ・人物・テキストがすべて 1 枚のラスター画像に固定されていました。「タイトルの位置だけ少しずらしたい」「背景だけ別案件に流用したい」が、Photoshop 系のソフトに持ち込まないと無理でした。マジックレイヤーは、その境界を Canva 内に閉じさせます。
1 週間の中で一番助かった瞬間は、月曜に作った Instagram 表紙のフォントを、木曜の朝に「やっぱり別の見出しフォントが合う」と気づいて差し替えるときでした。最初の生成からやり直す必要がなく、レイヤー単位で見出しテキストだけ差し替え、配置と色は維持。所要時間は 3 分です。これまでなら、生成 → 切り抜き → 再合成で 20 分以上かかっていた工程でした。
レイヤー名だけは自動では整いません。返ってくる名前が「テキスト 3」「画像 1」のままだと、木曜の自分が月曜の意図を読み解けなくなります。私は受け取った直後に「見出し-tier1」「装飾-背景」のようにロール名で付け替えるところまでを 1 セットにしています。
SNS リサイズと「1 投稿 → 5 サイズ」の運用ワークフロー
もう 1 つ運用で効いたのが、SNS リサイズです。1 つのキービジュアルを、先ほどの表にある 5 サイズへ展開しています。
@Canva 経由でやると、Gemini に「ストーリーズ用に縦に伸ばして、見出しは上 1/3 にまとめて」と一言伝えるだけで、新しいサイズの新規デザインが Canva 側に生成されます。次の 3 ステップで運用しています。
最初の縦長 (1080×1350) を @Canva で生成し、Brand Kit と内容を確定させる
その確定版を Gemini に追加プロンプトとして渡し、4 サイズ分のリサイズ案を順に生成
Canva 側でレイアウトの微調整(特に X ヘッダーの安全領域)を手作業で整える
順序を入れ替えて「5 サイズを一気に出してから内容を詰める」を試した週もありましたが、これは失敗でした。文言を 1 か所直すたびに 5 つ直すことになり、かえって時間が伸びます。確定してから展開する、の順序は守ったほうがよさそうです。
短縮時間を体感で語らないために、作業ログを 1 行ずつ残す
「速くなった気がする」は、翌月には根拠として使えません。導入週から、投稿 1 件ごとに工程と分数を JSONL で 1 行ずつ書き足すようにしました。手で書くのは投稿 1 件あたり 4 行なので、負担は 20 秒程度です。
# tools/worklog.py — 工程別の中央値と、前週比の短縮幅を出す
import json, sys
from collections import defaultdict
from statistics import median, mean
PHASES = [ "ideate" , "first_draft" , "revise" , "export" ]
def load (path):
rows = []
with open (path, encoding = "utf-8" ) as f:
for line in f:
line = line.strip()
if not line:
continue
r = json.loads(line)
if r.get( "phase" ) not in PHASES :
raise ValueError ( f "未知の phase: { r.get( 'phase' ) } " )
rows.append(r)
return rows
def by_phase (rows, week):
acc = defaultdict( list )
for r in rows:
if r[ "week" ] == week:
acc[r[ "phase" ]].append( float (r[ "minutes" ]))
return acc
def per_post_total (rows, week):
acc = defaultdict( float )
for r in rows:
if r[ "week" ] == week:
acc[r[ "post_id" ]] += float (r[ "minutes" ])
return list (acc.values())
if __name__ == "__main__" :
rows = load(sys.argv[ 1 ])
before, after = sys.argv[ 2 ], sys.argv[ 3 ]
b, a = by_phase(rows, before), by_phase(rows, after)
print ( f " { 'phase' :12s } { 'before' :>7s } { 'after' :>7s } { 'diff' :>7s } " )
for p in PHASES :
if not b[p] or not a[p]:
print ( f " { p :12s } { '-' :>7s } { '-' :>7s } 欠測" )
continue
mb, ma = median(b[p]), median(a[p])
print ( f " { p :12s } { mb :7.1f } { ma :7.1f } { ma - mb :+7.1f } " )
tb, ta = per_post_total(rows, before), per_post_total(rows, after)
print ( f " \n 合計 中央値 { median(tb) :.1f } → { median(ta) :.1f } 分 "
f "(平均 { mean(tb) :.1f } → { mean(ta) :.1f } / n= { len (tb) } → { len (ta) } )" )
phase を固定リストで検証しているのは、記録が「revise」「revising」「修正」に散らばって集計が壊れた経験があるためです。自由記述を許すと、3 日後には別の名前で書きます。
この 1 行記録の形式自体は新しく作ったものではなく、アプリの個人開発でリリース前の作業時間を測るのに使っていた雛形をそのまま持ってきました。工程名を差し替えるだけで別の作業にも効くのが、この記録の扱いやすいところだと思っています。
前週(連携なし・18 投稿)と導入週(連携あり・21 投稿)の出力がこちらです。
工程 前週 中央値 導入週 中央値 差分
案出し・文言確定 4.0 分 3.5 分 -0.5 分
初稿生成(縦長 1 枚) 5.5 分 1.5 分 -4.0 分
手直し 2.0 分 1.5 分 -0.5 分
書き出し・保存 0.5 分 0.5 分 ±0
1 投稿 合計 12.0 分 7.0 分 -5.0 分
平均は 12.4 分 → 7.6 分でした。中央値より平均のほうが縮まり幅が小さいのは、導入週に 1 件だけ 24 分かかった投稿があるためです。マジックレイヤーの分解がうまくいかず、結局 Canva 側で組み直した回でした。こういう外れ値は平均に隠れるので、中央値と併記する形に落ち着いています。
短縮のほぼ全量が「初稿生成」に集中している点は、導入前の予想と違いました。私は「手直しが減るはず」と考えていたのですが、手直しは 0.5 分しか動いていません。画面を切り替えずに初稿が出てくることの効きが大きく、生成物の質が上がったわけではない、というのが数字の読み方です。
5 サイズ展開も同じ要領で測ったところ、前週の中央値 62 分に対して導入週は 22 分でした。こちらは手作業の調整が残るため、初稿生成ほど極端には縮みません。
週末のブランド逸脱チェックを、目視から色差の数値に移す
運用してみて一番怖かったのは、生成のたびに色が 1 トーンずつズレていく現象です。1 枚では気づかず、1 か月分を並べたときに「先週と今週で違う赤を使っている」と分かります。目視の週次チェックは、疲れている週ほど甘くなります。
そこで、書き出した PNG とブランドパレットの色差を計算して、しきい値を超えたものだけを報告させるようにしました。人間の目が判断するのは、報告が上がってきた数枚だけです。
# tools/brand_drift.py — 書き出し画像とパレットの色差(ΔE76)を測る
# 事前準備: pip install pillow
import json, sys, glob
from PIL import Image
THRESHOLD = 5.0 # これを超えたら要確認
QUANTIZE_COLORS = 12 # 支配的な色だけを見る
MIN_SHARE = 0.02 # 面積 2% 未満の色は無視(アンチエイリアス除去)
def hex_to_rgb (h):
h = h.lstrip( "#" )
return tuple ( int (h[i:i + 2 ], 16 ) for i in ( 0 , 2 , 4 ))
def srgb_to_lab (rgb):
def lin (c):
c /= 255.0
return c / 12.92 if c <= 0.04045 else ((c + 0.055 ) / 1.055 ) ** 2.4
r, g, b = (lin(v) for v in rgb)
x = ( 0.4124 * r + 0.3576 * g + 0.1805 * b) / 0.95047
y = ( 0.2126 * r + 0.7152 * g + 0.0722 * b) / 1.00000
z = ( 0.0193 * r + 0.1192 * g + 0.9505 * b) / 1.08883
def f (t):
return t ** ( 1 / 3 ) if t > 0.008856 else 7.787 * t + 16 / 116
fx, fy, fz = f(x), f(y), f(z)
return ( 116 * fy - 16 , 500 * (fx - fy), 200 * (fy - fz))
def delta_e (a, b):
la, lb = srgb_to_lab(a), srgb_to_lab(b)
return sum ((x - y) ** 2 for x, y in zip (la, lb)) ** 0.5
def dominant (path):
"""支配的な色を (rgb, 面積比) で返す。"""
img = Image.open(path).convert( "RGB" )
q = img.quantize( colors = QUANTIZE_COLORS , method = Image. MEDIANCUT )
pal = q.getpalette()
total = img.width * img.height
out = []
for count, idx in q.convert( "P" ).getcolors(total):
share = count / total
if share >= MIN_SHARE :
out.append(( tuple (pal[idx * 3 :idx * 3 + 3 ]), share))
return out
if __name__ == "__main__" :
palette = json.load( open ( "brand_kit.json" , encoding = "utf-8" ))[ "colors" ]
flagged = 0
for path in sorted (glob.glob(sys.argv[ 1 ])):
for rgb, share in dominant(path):
name, d = min (
((n, delta_e(rgb, hex_to_rgb(h))) for n, h in palette.items()),
key =lambda t: t[ 1 ],
)
if d > THRESHOLD :
flagged += 1
print ( f " { path } : { name } から ΔE= { d :.1f } "
f "(面積 { share * 100 :.0f } % / RGB { rgb } )" )
print ( f " \n 要確認 { flagged } 件 / しきい値 ΔE> { THRESHOLD } " )
MIN_SHARE を入れているのが実務上の勘所です。最初はこれを付けずに走らせ、文字のフチのアンチエイリアスが毎回「逸脱」として報告されて使い物になりませんでした。面積 2% で切ると、報告されるのは背景・見出し・装飾といった意思のある色だけになります。
しきい値を 5.0 にしたのは、私自身の目で「別の色だ」と感じ始めるのがおおむねこのあたりだったためです。導入週の 21 投稿ぶんを流した結果がこちらです。
パレット色 最大 ΔE 要確認 所見
primary (#1B2A4A) 1.4 0 件 背景指定は安定。プロンプトで hex まで渡している効果
ink-black (#14161A) 2.1 0 件 本文色は許容範囲
off-white (#F4F1EA) 3.9 0 件 下地の写真に引かれてわずかに転ぶ
accent (#E0553B) 6.8 2 件 装飾の面で彩度が上がる。要修正
要確認になった 2 件はどちらもアクセント色でした。理由を追うと、装飾のグラデーションを言葉で頼んだ回に集中しており、hex を明示していた背景色ではズレが出ていません。ここから運用を 1 つ変えて、装飾面の色も生成器側で color_ref() を通すようにしました。翌週は 0 件です。
数値にした一番の効き目は、金曜の夜に「なんとなく気になる」で見返す作業が消えたことでした。報告が 0 件なら見ません。
1 週間運用して固まった、判断ルール
最後に、1 週間で固まった運用ルールを残します。
Gemini の会話セッションと、@Canva を使うデザインセッションは別ウィンドウに分ける
プロンプトは手で書かず生成器から組み立てます。色名は Brand Kit の辞書キーとしてのみ扱う
1 投稿あたり最初の縦長を確定させてから、リサイズ展開に進む(ターン数の節約より歩留まりを優先)
マジックレイヤーで受け取った直後に、レイヤー名をロール名(「見出し-tier1」など)へ付け替える
クライアント案件は別 Canva アカウントに分け、Gemini からは個人アカウントしか接続しない
プロンプトに社外秘の数値・氏名は書きません。Gemini 履歴に残る前提で運用する
週末の逸脱チェックは目視をやめ、ΔE のしきい値超過が報告された分だけ見る
導入前は 1 と 3 と 5 だけで運用していました。残りの 4 つは、指定漏れ・レイヤー名の放置・色ズレという、それぞれ実際に起きた失敗から足したものです。ルールが 7 つに増えたというより、失敗が 4 回あったと読むほうが正確だと思っています。
会話で完結するデザインが、手を動かす時間に返ってくる
導入週で、SNS 投稿の制作時間はトータルで 5 時間ほど浮きました。半分はスケッチの時間に戻り、もう半分は記事執筆と運用改善に回りました。
ひとつだけ、線引きとして書いておきたいことがあります。ここで AI に任せているのは、告知ビジュアルの制作という「作品を世に出す側」の作業です。展示に出す作品そのものは手で作っており、この境界は自分の中で動かしていません。ツールが速くなって浮いた時間を、境界のこちら側ではなく向こう側に戻せるのであれば、それがこの連携から得た一番の収穫だと感じています。
同じように個人で複数の発信媒体を持っている方は、まず作業ログの 1 行記録だけでも先に始めておくと、導入の前後で何が変わったかを後から言葉にできるはずです。お読みいただきありがとうございました。