> ## Documentation Index
> Fetch the complete documentation index at: https://help.teable.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# App Builderのベストプラクティス

> Teable App Builderを最大限に活用するための実践的なヒントとパターンを紹介します。

## 構築のヒント

### 1. 最初にデータを定義する

Teable App Builderは既存のTeableテーブルを基盤として動作します。**テーブルとフィールドがスキーマそのもの**であり、AIはUIとロジックの生成時にそれらを直接読み取ります。

そのため、構築を始める前にデータモデルを明確に定義してください。フィールド型、リンク、読み書きの経路が正確であるほど、AIが生成する成果物の品質が高くなります。

### 2. 構築前に計画する

データモデルを用意しても、すぐにUIの構築へ進まず、最初にAIと計画を立ててください。

たとえば、\*「まだコードを書かず、まず計画を立てましょう」\*と伝えます。解決する問題、対象ユーザー、おおよその機能一式を説明し、AIに構造化された提案を作成させます。内容を確認して調整し、計画に納得してから構築を開始します。

<Tip>最初に数分追加して方向性を揃えることで、後から何時間もの手戻りを避けられます。</Tip>

### 3. 小さく始める

すべての機能を1つのプロンプトへ詰め込まないでください。まず中核機能を説明して最小限の動作版を作り、その後、1つの操作、1つのスタイル調整、1つのロジックというように、項目を1つずつ追加します。

次へ進む前に、各変更を検証します。問題が発生しても、最初からやり直すのではなく、小さな変更を1つだけ元に戻せます。

### 4. 抽象的ではなく具体的に指示する

\*「もっと見栄えをよくして」*や*「操作をもっと自然にして」\*などの説明では、AIにほとんど情報が伝わりません。

効果的なプロンプトでは、**どのページの、どの領域で、どのような動作を求め、何を避けたいのか**を具体的に示します。スクリーンショットや参考UIの添付も非常に役立ちます。

<Tip>プロジェクトについて何も知らない優秀な人へ渡す概要書のように、プロンプトを作成してください。指示が正確であるほど、出力は想像したものに近づきます。</Tip>

### 5. 修正前に診断する

アプリが想定どおりに動作しない場合、AIへ\*「とにかく直して」\*と指示しないでください。曖昧な修正指示ではAIが手探りで変更を加え、途中で新しい不具合を持ち込むことがよくあります。

次の2段階で進めると効果的です。

<Steps>
  <Step title="最初にAIへ分析を依頼する">
    症状を説明し、まだコードには触れずに、考えられる原因と対応方法を一覧にするようAIへ依頼します。
  </Step>

  <Step title="方針を選び、実装する">
    最も妥当と思われる説明を選び、その方針に沿って進めるようAIへ指示します。
  </Step>
</Steps>

<Warning>修正を何度か連続して試しても失敗する場合は、最後に正常動作していたバージョンへ戻して、改めて開始してください。修正を重ね続けるより、通常は速く解決できます。</Warning>

### 6. バージョンのロールバックを活用する

AIとの会話ごとに変更が生成されます。推奨する進め方は、1つの機能モジュールを完成させ、動作を確認してから次へ進むことです。**複数の未完成機能を同時に扱わないでください。**

後から加えた変更によって問題が起きた場合は、最後の安定版へ戻し、より明確なプロンプトで再試行します。

## よくある質問

### App BuilderはNext.jsだけに対応しています

App Builderの実行環境（サンドボックス、プレビュー、ビルド）は**Next.js**を基盤としており、現在はAstro、Vite、Create React App、Vue、Svelteなど、他のフロントエンドフレームワークには**対応していません**。

Next.js以外のフレームワークを使用するようAIに依頼しても、常に拒否されるとは限らず、対応するコードを生成しようとする場合もあります。しかし、基盤となる環境に互換性がないため、**プレビューの起動に失敗します**。「プレビューを開始しています...」の状態から進まなくなり、その間も会話でクレジットが消費され続けます。

<Warning>
  Next.js以外のフレームワークを使用する必要がある場合は、独自のローカル環境で開発し、Teable API経由でデータへ接続することをおすすめします。
</Warning>

### 429エラーへの対応

<Warning>
  Teable APIは現在、**10 QPS**（1秒あたり10リクエスト）に制限されています。App Builderで生成したアプリでは、リクエスト処理を最適化していない場合、通常の利用でも429エラーが発生する可能性があります。エンジニアリングチームはAPIパフォーマンスの最適化に積極的に取り組んでおり、今後この上限を調整する場合があります。
</Warning>

対応方法は、大きく4つに分かれます。

<CardGroup cols={4}>
  <Card title="キャッシュ" icon="database">
    重複リクエストを減らします
  </Card>

  <Card title="ページネーションと一括処理" icon="layer-group">
    リクエストごとのペイロードを小さくします
  </Card>

  <Card title="デバウンスとスロットル" icon="gauge-high">
    リクエスト頻度を下げます
  </Card>

  <Card title="レンダリングの互換性" icon="window-restore">
    プレビューエラーを減らします
  </Card>
</CardGroup>

以降の各セクションでは、一般的な状況、修正方法、再利用できる参考プロンプトを示します。

**キャッシュ — 重複リクエストを減らす**

<AccordionGroup>
  <Accordion title="表示中心のページやダッシュボードで、読み込み時にリクエストが多発する" icon="bolt">
    **状況**: ダッシュボードページに複数のグラフ、統計カード、一覧があり、それぞれが別のテーブルへクエリを実行します。または、主に表示用のページであるにもかかわらず、訪問のたびにAPIへ直接アクセスします。どちらの場合も、ページ読み込み時の同時実行数が急増し、アクセスの増加によって429エラーが発生しやすくなります。

    **修正方法**: キャッシュしやすいレンダリングパターンを優先します。読み込み後にアプリのメモリへデータをキャッシュし（最初は1～3分のTTLが適切です）、その後の訪問で再利用します。画面外のコンポーネントを遅延読み込みし、リクエストのタイミングを分散します。それでも訪問のたびに再取得する場合は、キャッシュ戦略を強化するよう明示的にAIへ依頼します。

    <Tip>
      **参考プロンプト**: 「このページは表示中心です。キャッシュしやすいレンダリング方式を優先してください。ページ読み込み後、1分間のTTLでデータをローカルにキャッシュし、TTL期間中はAPIへ再リクエストせず、画面外のコンポーネントは500ミリ秒遅延させてください。」
    </Tip>
  </Accordion>

  <Accordion title="複数のコンポーネントが同じテーブルへクエリする" icon="copy">
    **状況**: 同じページにある3つのコンポーネントが同じテーブルのデータを必要とし、それぞれ独自のリクエストを送信しています。本来は1回で十分です。

    **修正方法**: データ取得を一元化し、同じデータセットを一度だけ読み込んで、コンポーネント間で共有します。

    <Tip>
      **参考プロンプト**: 「複数のコンポーネントが同じテーブルのデータを必要とする場合は、一度だけ取得して、すべてのコンポーネントで共有してください。重複リクエストを送信しないでください。」
    </Tip>
  </Accordion>

  <Accordion title="ページ移動時に再取得する" icon="arrows-rotate">
    **状況**: ユーザーがページ間を行き来します。変更がない場合でも、戻るたびに新たなデータ取得が実行されます。

    **修正方法**: キャッシュのTTL期間内は、再リクエストせず、以前に読み込んだデータを再利用します。

    <Tip>
      **参考プロンプト**: 「ユーザーがページへ戻ったとき、最後の読み込みから1分未満であれば、キャッシュデータを使用してください。APIへ再リクエストしないでください。」
    </Tip>
  </Accordion>

  <Accordion title="ドロップダウンが膨大な選択肢一覧を読み込む" icon="list">
    **状況**: ドロップダウンの選択肢として、テーブルのすべてのレコードを表示します。レコード数が多いと、その1回のリクエストだけでも負荷が高くなります。

    **修正方法**: 検索形式の選択ツールへ変更し、ユーザーが入力した後に一致するレコードだけを取得します。または、選択肢一覧をキャッシュします。

    <Tip>
      **参考プロンプト**: 「ドロップダウンでは最初にすべての選択肢を読み込まないでください。入力に応じて一致するレコードを取得するキーワード検索へ変更し、デバウンスを適用してください。」
    </Tip>
  </Accordion>

  <Accordion title="連動セレクターがリクエストを連鎖させる" icon="sitemap">
    **状況**: 1つのフィールドを選択すると、次の階層の選択肢が読み込まれます。複数階層の連動によって、1回の操作で複数のリクエストが発生します。

    **修正方法**: 関連データを一度事前読み込みしてローカルで絞り込むか、最初の読み込み後に連動データをキャッシュします。

    <Tip>
      **参考プロンプト**: 「読み込み後、連動セレクターの選択肢データをローカルへキャッシュしてください。ユーザーが親の選択肢を変更したら、再リクエストせず、キャッシュから絞り込んでください。」
    </Tip>
  </Accordion>

  <Accordion title="再レンダリングによって重複リクエストが発生する" icon="repeat">
    **状況**: 不適切な状態管理により、コンポーネントがレンダリングのたびにデータを再取得します。

    **修正方法**: レンダリングのたびではなく、特定のイベント（最初のマウント、明示的なユーザー操作）でデータ取得を実行します。安全策としてキャッシュを使用します。

    <Tip>
      **参考プロンプト**: 「最初のページ読み込み時または明示的なユーザー操作時にだけデータを取得してください。再レンダリング時には再取得せず、代わりにキャッシュデータを使用してください。」
    </Tip>
  </Accordion>
</AccordionGroup>

**ページネーションと一括処理 — リクエストごとのペイロードを小さくする**

<AccordionGroup>
  <Accordion title="ページネーションのない一覧またはテーブル" icon="table-list">
    **状況**: すべてのレコードを一度に読み込むと、データセットが大きくなるにつれてAPI呼び出しが急増します。

    **修正方法**: ページネーションを使用し、現在のページのデータだけを取得します。

    <Tip>
      **参考プロンプト**: 「1ページに20行を表示してください。ユーザーが次のページへ移動したときにだけ読み込んでください。すべてを一度に読み込まないでください。」
    </Tip>
  </Accordion>

  <Accordion title="リンクデータを行ごとに取得する（N+1）" icon="link">
    **状況**: 一覧を読み込んだ後、各レコードのリンク先テーブルの詳細を1件ずつ取得します。50件のプロジェクトを読み込んだ後で、所有者を50回検索すると、瞬時に50件の追加リクエストが発生します。

    **修正方法**: リンクデータを行ごとではなく、すべて一括で取得します。

    <Tip>
      **参考プロンプト**: 「一覧を読み込むとき、すべてのリンクデータを1回のリクエストで一括取得してください。レコードをループして、リンク情報を個別に取得しないでください。」
    </Tip>
  </Accordion>

  <Accordion title="一括更新時に行ごとに書き込む" icon="pen-to-square">
    **状況**: 複数のレコードを一括更新するとき、1回の一括リクエストではなく、レコードごとに更新リクエストを送信します。

    **修正方法**: 一括更新APIを使用し、すべての変更を1回の呼び出しで送信します。

    <Tip>
      **参考プロンプト**: 「一括操作では、複数のレコード変更を1回の一括リクエストへまとめてください。レコードごとに更新を送信しないでください。」
    </Tip>
  </Accordion>

  <Accordion title="ループ内でAPIを呼び出す" icon="rotate">
    **状況**: `for`ループでレコードを1件ずつ処理し、各反復でAPIを呼び出します。

    **修正方法**: 最初にすべてのIDを収集し、その後、1回の一括リクエストを送信します。

    <Tip>
      **参考プロンプト**: 「ループ内でAPIを呼び出さないでください。最初に必要なすべてのIDを収集し、その後、1回の一括リクエストを送信してください。」
    </Tip>
  </Accordion>
</AccordionGroup>

**デバウンスとスロットル — リクエスト頻度を下げる**

<AccordionGroup>
  <Accordion title="検索またはフィルターにデバウンスがない" icon="magnifying-glass">
    **状況**: 検索ボックスでキーを入力するたびにリクエストが発生します。4文字のクエリを入力すると、4件のリクエストが発生します。

    **修正方法**: 入力へデバウンスを適用します。ユーザーが入力を止めてから300～500ミリ秒待って、リクエストを送信します。

    <Tip>
      **参考プロンプト**: 「検索入力にデバウンスを適用してください。ユーザーが入力を止めてから300ミリ秒後にだけリクエストを送信し、入力中は送信しないでください。」
    </Tip>
  </Accordion>

  <Accordion title="ユーザーが短時間に操作を繰り返す" icon="hand-pointer">
    **状況**: 送信ボタンの連打、フィルターの素早い切り替え、高速なページ移動など、それぞれの操作ですぐにリクエストが発生します。

    **修正方法**: デバウンスまたはスロットルを適用します。二重送信を防ぐため、リクエストが完了するまで送信ボタンを無効にします。

    <Tip>
      **参考プロンプト**: 「クリック後は送信ボタンを無効にし、リクエストが完了したら再び有効にしてください。フィルター変更にデバウンスを適用し、300ミリ秒以内の連続した変更では1件のリクエストだけを送信してください。」
    </Tip>
  </Accordion>

  <Accordion title="フォームの自動保存が過剰に実行される" icon="floppy-disk">
    **状況**: フィールドを変更するたびに、すぐに保存します。フォームへの入力で十数回の書き込みが発生することがあります。

    **修正方法**: ボタンをクリックする明示的な保存へ切り替えるか、自動保存へデバウンスを適用し、編集が途切れた後に一度だけ実行します。

    <Tip>
      **参考プロンプト**: 「フィールドを変更するたびに保存しないでください。明示的にボタンをクリックしたときに保存するか、ユーザーが編集を2秒間停止した後に一度だけ自動保存してください。」
    </Tip>
  </Accordion>

  <Accordion title="ポーリング間隔が短すぎる" icon="clock">
    **状況**: 数秒ごとにデータが更新され、継続的に高頻度のトラフィックが発生します。

    **修正方法**: ポーリング間隔を妥当な時間（30秒以上）へ延長するか、手動更新へ切り替えます。

    <Tip>
      **参考プロンプト**: 「自動更新の間隔を60秒に設定してください。ユーザーが必要に応じて最新データを取得できるよう、手動更新ボタンを追加してください。」
    </Tip>
  </Accordion>

  <Accordion title="複数のコンポーネントが個別にポーリングする" icon="timer">
    **状況**: ページ上の複数のコンポーネントが、それぞれ独自のポーリングタイマーを設定しています。合計負荷によって、簡単に上限を超えます。

    **修正方法**: ポーリングを一元化します。定期的な取得を1回実行し、その結果を必要とするすべてのコンポーネントへ配布します。

    <Tip>
      **参考プロンプト**: 「各コンポーネントに独自のポーリングタイマーを設定させないでください。1つの更新機構を使用して、スケジュールに従ってすべてを取得し、データを各コンポーネントへ配布してください。」
    </Tip>
  </Accordion>
</AccordionGroup>

**レンダリングの互換性 — プレビューエラーを減らす**

<AccordionGroup>
  <Accordion title="グラフ、地図、ブラウザー専用コンポーネントがプレビューで失敗する" icon="chart-line">
    **状況**: ページが`window`、DOMの寸法、その他のブラウザー専用APIに依存するグラフ、地図、ライブラリを使用しており、プレビューにエラー、空白画面、ハイドレーションの不一致が表示されます。

    **修正方法**: このようなコンポーネントは、サーバー上で直接レンダリングせず、ブラウザーで読み込むほうが安全な場合がよくあります。プレビューの問題が続く場合は、ブラウザー専用の読み込みパターンへ切り替えるよう明示的にAIへ依頼します。

    <Tip>
      **参考プロンプト**: 「このコンポーネントはブラウザー環境に依存しています。プレビューのレンダリングエラーやハイドレーションの不一致を避けるため、クライアントでのみ読み込んでください。」
    </Tip>
  </Accordion>
</AccordionGroup>

<Note>
  AIは誤ることがあります。回答を必ず再確認してください。
</Note>
