appllama-app-design-skill について
Appllama App Design Skillは、実在するアプリの画面とネイティブの設計慣習を参考に、モバイルアプリの画面を作るエージェントを支援します。ビジュアル、ナビゲーション、モーション、画面状態を扱います。
主な機能
- 01実在アプリの画面を調査
- 02ネイティブの設計慣習を適用
- 03ナビゲーションと遷移を設計
- 04ビジュアルの一貫性を確認
- 05画面状態を一通り設計
活用シーン
- 01モバイルアプリの画面設計
- 02ナビゲーションとネイティブ動作の確認
- 03シミュレーター検証前の画面確認
MCP 対応
Appllama MCPに接続している場合、参考画面の取得を推奨します。このスキル自体は設計・実装の指針を示すもので、MCPサーバーのツールは説明していません。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ appllama/ appllama-skills --skill appllama-app-design-skillインストール後、Claude Code で/appllama-app-design-skillを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/image-assets.mdmotion.mdnative-controls.mdperformance.mdsimulator-loop.md詳細
Appllama アプリデザインスキル
世界最高水準のデザインを誇るアプリと並んで、スマートフォンに表示される画面を作成します。ユーザーはアプリを起動して数秒以内に、あなたの成果をそれらのアプリと比較します。このスキルでは、その水準と到達するための方法を定めています。
最優先事項:描く前に調査する
同じ画面をトップクラスのアプリがどのように解決したか調べられるなら、想像だけで画面をデザインしてはいけません。実際にリリースされ、売上ランキングに入っているアプリには、何千時間にもおよぶデザインの反復と A/B テストの成果が反映されています。画面に取り組むときは、まず調査から始めます。
- Appllama MCP が接続されている場合は、作成するカテゴリと画面タイプの実際の画面を取得します(具体的な調査手順は
appllama-usageスキルを参照してください)。UI コードを1行でも書く前に、20~30画面を調べます。 - ピクセルではなくパターンを抽出します。レイアウトの骨組み、情報の階層、コントロールの選択、余白のリズム、メインの CTA の配置、イラストとテキストのみを使う箇所の違い、進捗の伝え方などを確認します。 注:Appllama の画像と動画には、左上に小さな Appllama の透かしが入っています。これは出所を示すもので、デザイン要素ではありません。画面を確認するときは無視してください(ステータスバーや戻るボタンの上に重なる場合があります)。作成するものに再現してはいけません。
- その後、自分の画面をデザインします。実績のある骨組みに、自社プロダクトの個性を加えます。競合の画面をそのままコピーするのは怠慢であり、法的リスクもあります。一方で、ユーザーがすでに知っている慣習をすべて無視した画面をリリースするのは、さらに悪いことです。
プラットフォームの基本設定
デフォルトのスタックに関する前提(プロジェクトにすでに異なる設定がある場合のみ変更してください):
- Expo + Expo Router、React Native、TypeScript。
- アニメーションには
react-native-reanimated、ジェスチャーにはreact-native-gesture-handler、増加する可能性のあるリストには@shopify/flash-list(または FlashList v2)を使用します。 - 画像には
expo-image(iOS ではsource="sf:name"による SF Symbols も使用)、動画にはexpo-video、音声にはexpo-audioを使用します(非推奨のexpo-avは使用しないでください)。 - インセットには
react-native-safe-area-contextを使用します。ノッチの数値をハードコードしてはいけません。 - コンパイル時のプラットフォーム判定には
Platform.OSよりprocess.env.EXPO_OSを使用します。
ネイティブ品質の原則
これらは「ラッパーに入れたウェブページ」と「ネイティブアプリ」を分ける細部です。 どれかに違反していれば、スタイルの好みではなく指摘事項です。
- 初日から両テーマに対応したセマンティックカラーを使う。 システム/セマンティックカラーのトークンを使用します
(例:iOS では
expo-routerのColor、つまりColor.ios.label、Color.ios.secondarySystemBackground。Android では Material の動的カラー)。 すべての画面は、完成とみなす前にライトモードとダークモードの両方で 正しく表示される必要があります。セマンティックカラーオブジェクトを Reanimated の アニメーションスタイルに渡してはいけません。まず文字列に解決します。 - 独自に作り直すのではなく、ネイティブコントロールを使う。 スイッチ、スライダー、 セグメントコントロール、コンテキストメニュー、日付ピッカーには、ネイティブコントロール または忠実なラッパーを使います。iOS より 50 ms 違うアニメーションをする独自のトグルは、 すぐに偽物のように感じられます。
- アイコンには SF Symbols/Material Symbols を使う。 iOS では SF Symbols
(
sf:ソースを使うexpo-image、またはexpo-symbols)を優先します。ウェイト、 オプティカルサイズ、Dynamic Type の挙動が引き継がれます。1 つの画面で 3 種類の アイコンファミリーを混在させないでください。 - タイポグラフィは階層構造です。 プラットフォームの文字スタイル(iOS の
ラージタイトル/タイトル/見出し/本文/脚注)を使います。1 画面につきディスプレイサイズは
1 種類にします。数値、時刻、価格には表形式の数字(
fontVariant: ['tabular-nums'])を 使います。ユーザーがコピーする可能性のあるデータにはText selectableを使います。 - 連続的な角丸を使う。 角丸の長方形にはすべて
borderCurve: 'continuous'を 指定します。スクワークルは、iOS らしい使い心地を最も手軽に実現できる方法です。 - シャドウには CSS の
boxShadowを使い、従来のshadow*/elevationプロパティは使わない。 シャドウは装飾ではなく、高さの表現に使います。アプリ内の高さ表現システムは 1 つに統一します。 - 余白のリズムを整える。 基準となる単位(4 または 8)を決め、常にそれに従います。
マージンを重ねるより、flexbox の
gapを優先します。ScrollView のパディングは ScrollView 自体ではなくcontentContainerStyleに指定します。 - セーフエリアと Dynamic Island もデザインの一部です。 コンテンツが Dynamic Island/ ステータスバーの下にスクロールした状態(ぼかし/フェードの処理が保たれるか)、 ホームインジケーターがある状態(画面下部の CTA が重ならないか)、および対応している場合は 横向きで、画面を確認する必要があります。
- ナビゲーションタイトルはナビゲーターに任せる。 可能な限り、独自に作ったヘッダーではなく、 スタックのネイティブタイトル(および iOS のラージタイトルの折りたたみ挙動)を使います。
- 触覚フィードバックは句読点です。 値が段階を進むときは選択時のクリック感、元の位置に 戻るときは軽い衝撃、結果には成功/エラーの通知を、視覚効果と同じフレームで、それぞれの ユーザー操作につき 1 回だけ加えます。ただし、フィードバックだけに頼ってはいけません。 スクロール中やループ内では使いません。
- 数値はデータベースのようではなく、製品らしく整形する。 1.4M、38k、$4.99 のように 表示します。末尾のゼロは取り除きます。日付はローカライズします。
- ルートのスクロール動作: 内容があふれる可能性のある画面では、コンテンツを
contentInsetAdjustmentBehavior="automatic"を指定した ScrollView(ルートの最初の コンポーネント)で囲みます。Dimensions.get()ではなくuseWindowDimensionsを使います。
ナビゲーションの原則
ナビゲーションはスクリーンショットには映らない画面の一部ですが、ユーザーは10秒でその影響を感じます。画面遷移のたびに、次の3つの問いに答える必要があります。遷移先はここからどこか、ユーザーは戻ってこられる必要があるか、そして戻る操作(シェブロン、iOSのエッジスワイプ、Androidのハードウェアバック)はその後どう動作するかです。
- pushは深い階層へ進み、replaceは次へ進みます。 ユーザーがここに戻りたくなる場合は
router.pushを使います。戻っても状況がすでに変わっていて意味がない場合はrouter.replace/<Redirect>を使います。「このフローを終えてXに移動する」場合はrouter.dismissTo(href)を使います。戻る操作で取り消すのはナビゲーションであり、イベントではありません。 - 表示方法には意味があります。 手順のある独立したタスクには、独自のスタックとキャンセル/完了操作を持つ
presentation: 'modal'を使います。短い割り込み(ピッカー、フィルター、アイテムのオプション)には、detentsとスワイプで閉じる操作を備えたformSheetを使います。没入型コンテンツには、明示的な閉じる操作を備えたfullScreenModalを使います。画面がまだ見えている状態でその上に浮かぶもの(確認カード、ライトボックス、コーチマーク)には、transparentModalオーバーレイを使います。破壊的な操作の確認にはアクションシートを使い、アイテムの操作にはネイティブのコンテキストメニューを使います。共有/Web/写真の選択には、再構築したルートではなく、必ずシステムコントローラーを使います。2つ目のステップが追加されるシートは、最初からモーダルにすべきです。リンクから開けるものはルートであり、useStateで管理するシートではありません。 - 後戻りできない画面遷移はスタックから外します。 壁アプリでのサインイン、オンボーディングの完了(スキップを含む)、購入、セッションの完了には
Stack.Protectedでアクセスを制御し、replaceで遷移先へ移動します。これにより、戻る操作で以前の状態に再び入ることはありません。Androidでホームから戻るとアプリが終了し、ログイン画面は表示されません。有料のペイウォールが再び開くこともありません。ただし、ユーザーがいた場所は維持します。1つの操作(保存、フォロー、購入)のためにサインインを求める場合は、タップした画面上にモーダルを表示し、サインイン後にそこで操作を完了できるようにします。機能画面から開いたペイウォールは閉じるとロック解除された機能画面に戻り、そこからreplace('/(tabs)')で遷移させてはいけません。 - 戻る操作をブロックしてよいのは、ちょうど2つの場合だけです。 目に見える進行状況が表示される、数秒かかる取り消し不能なリクエストの処理中と、未保存の作業があるモーダル(先に確認する場合)です。どちらもモーダルのルート画面で
usePreventRemoveを使います。画面内の一時的な状態(選択モード、展開された検索、開いている画面内シート)では、最初の戻る操作を受け止め、その次の戻る操作で画面を離れます。その他、戻る操作を妨げるもの(申し込みフロー、評価のプロンプト)は不具合です。それ以外の場所ではエッジスワイプが機能します。 - タブは同列です。 タブ間でスライドせず、各タブは独自のスタックを維持します。選択中のタブを再タップするとルートまで戻ります。コンポーザー、プレーヤー、チェックアウトなど、ユーザーの注意を全面的に必要とする画面は、タブの上にあるルートスタックに配置します。ディープリンクでは、その下に実際のスタックを用意します(
initialRouteName/withAnchor)。コールドスタートでは状態に応じた画面を表示し、セッション状態の解決が完了するまでスプラッシュ画面を維持します。ホームの前にログイン画面が一瞬表示されることはありません。 - 見た目だけでなく、遷移の文法を学びます。 Appllamaで優れたフローを実際にたどり、各ステップがpush、モーダル、シートのどれなのかに注目し、その一貫性を取り入れます。
ありきたりを避けるためのルール
AI で構築されたアプリは見た目が似通っており、ユーザーは数秒で「テンプレート」と判断します。 以下はそれぞれ デフォルトで禁止 です。ブランドから明示的に求められ、かつこのプロダクトに適している理由を説明できる場合は、いつでも例外を認められます。
- AI のデフォルトスタイルは禁止です。 紫やインディゴのグラデーション CTA に光彩を付ける、すべてのカードをグラスモーフィズムにする、ヒーローにメッシュグラデーションを使う、些細なイベントに紙吹雪を散らす、見出しにきらめきを添える――それはモデルのお決まりのスタイルであり、デザインではありません。配色、素材、レイアウトは、調査した参考画面に基づいて決めてください。特に求められてもいないのに思いつくお決まりのスタイルには頼りません。
- アクセントカラーは1色に固定します。 アクセントカラーを1色選び、すべての画面で同じ色を使います。ある画面では青の CTA、次の画面ではティールを使うことや、7画面目で新しい色相を登場させることは禁止です。アプリの大部分はニュートラルカラーで構成し、アクセントカラーは重要な箇所(主要アクション、アクティブ状態、進捗)に使います。
- グレーの系統は1種類にします。 暖色系のグレーか寒色系のグレーのどちらか一方にし、1つのアプリで両方を使うことは禁止です。
- 形状を固定します。 角丸のスケールを1つ決め、「アクションはピル型、カードは16、入力欄は8」のようにルールとして明示し、例外を認めません。明示されたルールなしに異なる角丸を混在させると、寄せ集めの印象になります。
- アイコンに絵文字を使いません。 アイコンには SF Symbols/Material Symbols を使います(忠実度ルール3)。絵文字を使えるのは、プロダクトの語り口が本当にチャットらしい、または遊び心のある場合に限ります。コンテンツ内で控えめに使い、UI の装飾には使いません。
- 意図ごとにラベルを1つに統一します。 「始めましょう」「今すぐ開始」「開始する」は同じ意図です。表現を1つ選び、その意図が現れるすべての箇所で使います。
- 強調は同じ書体の範囲内で行います。 同じ書体の太さやイタリックで単語を強調します。視覚的な変化を狙って、サンセリフ体の見出しにセリフ体の単語を混ぜる(またはその逆)のは素人っぽいやり方です。
- 理想的な状態だけでなく、すべての状態の遷移を実装します。 成功状態だけを静的に表示するのは、よくある失敗です。スケルトンは最終レイアウトの形状に合わせ、空の状態は内容を整え、データを入力する方法も示します。エラーはインラインで具体的に表示します。
- ありきたりになっていないかの事前確認は機械的に行います。 フローをシミュレーターで確認する前に、次の数を数えます。異なるアクセントカラーの色相(1色であること)、異なる角丸(すべて明示したスケール内であること)、UI の装飾に使われた絵文字(0個)、ブランド上の理由がないグラデーション(0個)、同じ意図に対する重複したラベル(0個)。数が合わなければ修正が必要です。判断の余地はありません。
モーションの原則
モーションは、仕上がりを大きく高める一方で、最もやりすぎやすい要素です。 次の順番で判断します。
- まず頻度の基準を確認します。 1日に100回以上使う操作(タブ切り替え、 キーボード、スクロール、戻る)にはプラットフォームのデフォルトのみを使います。1日に 数十回使う操作(押下、行の選択)は、ほとんど気づかない程度にし、150 ms 未満にします。たまに使う操作(シート、モーダル、トースト)には標準的なモーションを使い、 楽しさを演出するのは、まれな初回体験だけにします。タブはスライドさせず、 画面遷移はネイティブのままにします。 コードを一行も書かずにこの基準を満たせれば成功です。迷ったら、アニメーションを 削除するのが最善です。
- 目的を一言で表します — フィードバック、空間的な連続性、状態変化、 唐突な切り替わりの防止、説明、楽しさ — できない場合は実装しません。ユーザーが読んでいるデータを、装飾のために動かしてはいけません。
- 指で操作するなら、スプリングを使います。 現在の値から開始し(つかんだときに取得)、
離すときの速度をスプリングに引き継ぎ、勢いを予測してターゲットを決め、フリックで確定できるようにします。境界を越えたらラバーバンドのように戻り、動作中もつかめるようにします。アプリ全体でモーションの語彙を統一します —
{ duration: 400, dampingRatio: 1 }で落ち着かせ、シートには{ 300, 0.8 }を使います — バウンスはジェスチャーに勢いがあった場合のみ使います。 - それ以外はタイミングで制御し、300 ms 未満で強いイーズアウトを使います
(
Easing.bezier(0.23, 1, 0.32, 1)— 組み込みのカーブでは弱すぎます。登場時にイーズインは使いません)。 押下時のフィードバックは押し始めに反映し、100–150 ms とします。ボタンとカードは 0.97 に縮小し、リスト行は背景をハイライト(拡大縮小は不可)し、バーのボタンは不透明度を変えます。退出は登場より速くし、入ってきた方向へ戻します。scale(0.95)とフェードで登場させ、scale(0)は使いません。メニューは起点から広げます(中央配置のモーダルは除きます)。 - ジェスチャーからアニメーションへの処理で JS スレッドに切り替えてはいけません。
worklet と共有値(
.get()/.set()、scheduleOnRN— Reanimated 4 のrunOnJS— はジェスチャー終了時のみ)を使い、transform/opacityのみをアニメーションさせます。再利用されるリスト行にenteringを設定せず、ヘッダーの高さをアニメーションさせません(固定クリップ内で移動させます)。キーボードに追従する UI にはreact-native-keyboard-controllerを使います。キーボードリスナーと推測した時間を組み合わせてはいけません。 - Reduce Motion に配慮します。空間的なモーションはクロスフェードに置き換え、ネイティブ遷移はシステムに任せます。
- 目標は、主要なフローで 60 fps を維持することです。対応する中で最も低速なデバイスのリリースビルドで計測します。Expo Go と開発ビルドでは、まさに検出すべきジャンクが隠れてしまいます (references/performance.md)。録画を一度は感覚を確かめるために、もう一度はフレーム単位で確認するために、さらに翌日に新鮮な目で見直します。
状態アーキテクチャ
使い心地の良い画面は、状態管理が目立たない画面です。
- サーバー状態には TanStack Query(またはプロジェクトで同等のもの)を使い、キャッシュ、
再試行、楽観的更新を行います。
useEffectとfetchの組み合わせは使いません。 - クライアント状態は、小規模なアトミックストア(Zustand/Jotai)で管理します。広範囲に及ぶ「アプリ状態」のコンテキストは、UI を重く感じさせる再レンダリングの連鎖を引き起こします。
- 一時的な UI 状態(開閉、フォーカス、スクロール)は、コンポーネント内にとどめます。
- デフォルトで楽観的に更新します。タップは即座に反映し、バックグラウンドで整合させ、失敗したら明確にロールバックします。
- 入力頻度の高い領域では、非制御の
TextInputを使います。制御された入力は、タイピング時のジャンクの主な原因トップ 3 の一つです。 - クライアント状態が小さく、レイテンシが問題になる場合は、AsyncStorage ではなく MMKV に永続化します。
体感パフォーマンス
- スケルトンはコンテンツの形がわかっている場合にのみ使い、それ以外では段階的に表示します。一部更新のために全画面スピナーを表示してはいけません。
- すべてのリストに FlashList を使い、安定したキーを指定します。
- 次の画面のデータは、ナビゲーション完了時ではなく、押し始めにプリロードします。
- 画像には適切なサイズのソース、リスト内では
recyclingKeyを指定したexpo-image、プレースホルダーには thumbhash/blurhash を使います。 - コールドスタート時の TTI とバンドル管理については references/performance.md を参照してください。計測 → 最適化 → 再計測のサイクルを適用し、やみくもにメモ化してはいけません。
画像・イラスト素材
画面にイラスト、空状態のアート、ヒーロー画像、またはシンボルセット以外のアイコンが必要な場合:
- 利用可能な最良の画像モデル(接続されている場合は、画像生成ツールや Higgsfield MCP/CLI など)で、最高品質の設定を使って素材を生成し、その後 @1x/@2x/@3x に縮小します。拡大はしないでください。
- アプリごとにビジュアル言語を統一します。スタイル(グラデーションメッシュ、フラットなデュオトーン、3D クレイ、手描き、マスコット調)を選び、すべての素材を同じスタイル、同じパレット、同じライティングで生成します。スタイルの混在した素材セットは、テンプレートの使い回しに見えてしまいます。
- サーフェスカラーに合わせた透明または単色の背景を指定します。合成時のアーティファクト(白い縁、色の合わないマット)は、必ず作り直してください。
- 素材の全パイプラインとプロンプトのパターン: references/image-assets.md。
シミュレーターでの反復(必須)
実行中の画面を実際に見るまで、その画面は完成したとは言えません。次の手順を繰り返します。
- 実装 → iOS Simulator(または Android エミュレーター)で起動します。
- スクリーンショットを撮って実際に確認します。配置、視覚的な中央揃え、間隔のリズム、長いコンテンツでの切り詰め、ダークモード、XL での Dynamic Type を確認します。
- 以下の全モーション確認を実行します。スクリーンショットで確認できるのはレイアウトだけで、モーションについては何も証明できません。
- 修正して、再起動し、もう一度確認します。欠陥が見つからなくなるまで繰り返し、その後 references/simulator-loop.md のチェックリストをもう一度実行します。
コードレビューだけで画面の完成を宣言してはいけません。「問題なさそう」で終わらせず、「100% のズームで欠陥が見つからない」状態を目指してください。
全モーション確認(必須、フローごと)
すべてのフローは、シミュレーター内で静止画ではなく動画として評価します。フロー全体を最初から最後まで画面録画し(xcrun simctl io booted recordVideo flow.mov)、次のすべてを実際に操作します。
- すべての画面遷移、プッシュ/ポップ、タブ切り替え
- すべての戻る操作(シェブロン、端からのスワイプ、Android のハードウェア戻るボタン)。また、サインイン、オンボーディング完了、購入、セッション完了など、戻れない画面に進んだ後は、戻る操作を試し、以前の状態に戻れないことを確認します。
- すべてのモーダルとシート:表示、ドラッグ、閉じる操作を行い、ドラッグ中のキャンセルも試します。
- キーボードの表示と非表示の両方:表示時はレイアウトが滑らかに移動するか、フォーカス中の入力欄が見えるかを確認し、非表示時は何かが急に切り替わらないかを確認します。
- すべてのユーザー操作:押下状態、ジェスチャーの完了、途中で中断したジェスチャー、連続タップ、スクロールの端でのフリック
録画を2 回確認します。1 回目は全速で操作感を確かめ、2 回目はコマ送りで確認します。次の点に注目します。
- フレーム落ちやカクつき。すべての遷移で安定して60 fpsを維持できているかを、感覚ではなく計測して確認します。
- 1 フレームだけのちらつき:初回描画が白色またはスタイル未適用、遷移中にテーマが誤ったフレーム、サーフェスが一時的に誤ったトークンで描画されることによる色のちらつき
- レイアウトの急な移動、二重描画によるちらつき、コンテンツに食い込んだり行き過ぎたりするスプリング、表示後に再配置される要素
録画全体が、最初から最後まで滑らかで、ネイティブアプリのように動作し、UX 上の不具合がまったくない状態でなければなりません。たった 1 フレームでも不具合があれば、そのフローは未完成です。
画面ごとの完了条件
- この画面タイプの実際の参考画面を10件以上調査し(利用可能な場合はAppllama MCPを使用)、採用したパターンを説明できる
- ナビゲーションを明確にする:この画面の種類(プッシュ/モーダル/シート/ オーバーレイ/置き換え)、iOSとAndroidでこの画面から戻るとどうなるか、そして — 一方向にしか進めない状態の背後では — 戻っても以前の状態に再び入れないこと
- シミュレーターでライトモードとダークモードを確認する
- セーフエリア/Dynamic Island/ホームインジケーターを確認する
- 長いコンテンツ、空、読み込み中、エラーの各状態を設計し、デフォルトに任せない
- モーション:フロー全体を画面録画して細部まで確認する — 表示、押下、 画面遷移、モーダル、キーボード — ネイティブらしい動作で、グリッチや 色の誤ったフレームがないこと。Reduce Motionを尊重し、サポート対象で最も 遅いデバイスのリリースビルドで60 fpsを測定する
- Dynamic Type XLでもレイアウトが崩れない。必要な箇所ではテキストを選択できる
- すべてのタップ対象が44pt以上。両方のテーマでコントラスト基準を満たす
- アセット:スタイルの系統を統一し、@3xでも鮮明で、合成によるハローがない
- リストのサーフェスを仮想化する。制御入力のカクつきや再レンダリングの嵐がない (推測ではなく、プロファイリングで確認する)
参考資料
| ファイル | 読み込むタイミング |
|---|---|
| references/native-controls.md | iOSとAndroidのネイティブコントロール、メニュー、ピッカー、シートを選択・接続するとき |
| references/motion.md | Reanimatedを使う作業全般:ジェスチャー、画面遷移、スプリング、レイアウトアニメーション |
| references/performance.md | カクつき、TTIの遅延、大きなバンドル、メモリリーク、プロファイリングの方法 |
| references/image-assets.md | 画像モデルでイラスト/アイコン/ヒーローアートを生成するとき |
| references/simulator-loop.md | 最終確認チェックリストとデバイスマトリクス |