GPT-6 Intelligent UI入門——生成UI案をFirestoreでレビューする
OpenAIのGPT-6 Intelligent UI発表を題材に、Next.js + FirestoreでAIが提案した画面仕様を監査しながら業務アプリへ取り込む実践手順を解説します。

はじめに
AIに業務画面の改善案を相談していると、こんな場面が増えてきました。
| 場面 | 起きがちな問題 |
|---|---|
| 問い合わせ一覧の絞り込みUIを考える | 見た目の案は出るが、誰が採用したか残らない |
| 管理画面のカード配置をAIに提案させる | 実装可能性、アクセシビリティ、権限条件の確認が後回しになる |
| 顧客向けフォームをAIで素早く作る | その場では便利でも、監査ログや差分レビューに乗らない |
OpenAIは2026年10月7日に、ChatGPT向けの GPT-6 and Intelligent UI を発表しました。公式発表では、GPT-6がテキスト、ビジュアル、ボタン、フォーム、チャートなどを組み合わせ、会話の中で使えるインタラクティブなUIを返せるようになったと説明されています。また、この更新はChatGPTのChat体験に適用されるもので、WorkやCodexを動かすモデルはこのリリースでは変わらないとも明記されています。
本記事では、架空の問い合わせ管理SaaS「PanelDesk」を題材に、Intelligent UIの考え方を自社のNext.js App Router + Firestore + TypeScript構成へ安全に取り込む方法を扱います。ポイントは、AIが作ったUIをそのまま本番に流すことではありません。AIの提案を「画面仕様案」として保存し、人間レビュー、実装、検証へ渡せる台帳を作ることです。
参考にした一次情報は次の通りです。
- OpenAI: GPT-6 and Intelligent UI for everyone
- OpenAI: A model guide for the GPT-6 family
- OpenAI API Changelog
何が新しいのか
OpenAIの発表では、Intelligent UIは質問内容に応じて、比較なら横並び、説明なら図解、作業なら小さなツールのように、応答形式を選び分ける方向性として紹介されています。従来の「文章で答えるAI」から、「会話の中で操作できるUIを組み立てるAI」へ寄っているのが大きな変化です。
ただし、業務アプリの開発では、ChatGPT上で便利なUIが見えた瞬間に、そのまま本番画面へ採用するわけにはいきません。ユーザー権限、個人情報、入力バリデーション、アクセシビリティ、既存デザインシステムとの整合、ログ保存を確認する必要があります。
PanelDeskでは、AIの提案を「実装済みUI」ではなく「レビュー対象のUI仕様」として扱います。これにより、AI活用の速度を保ちながら、チーム開発で必要な責任分界を残せます。
設計方針
まず、AIに自由なHTMLや任意のReactコードを生成させるのではなく、アプリ側が許可した部品だけを使う仕様にします。
| 項目 | 採用する方針 |
|---|---|
| UI部品 | metricCard、filterTabs、dataTable、actionPanel のように許可リスト化 |
| データ参照 | Firestoreのコレクション名とフィールド名を明示 |
| 実装判断 | AIの提案は draft として保存し、人間が approved にする |
| 危険操作 | 削除、課金、外部送信は必ず別レビュー |
| 記録 | 入力、提案、レビューコメント、採否理由をFirestoreに保存 |
この設計なら、Intelligent UI的な「その場で画面を組み立てる」体験を参考にしつつ、自社アプリでは監査しやすい形にできます。
ハンズオン1: UI提案の型を定義する
PanelDeskでは、問い合わせ一覧の改善案を uiProposals コレクションへ保存します。まずはTypeScriptで、AIや人間が扱う仕様の形を固定します。
// src/types/uiProposal.ts
export type UiComponentKind =
| "metricCard"
| "filterTabs"
| "dataTable"
| "actionPanel";
export type UiProposalStatus =
| "draft"
| "approved"
| "rejected"
| "implemented";
export type UiProposalComponent = {
id: string;
kind: UiComponentKind;
title: string;
purpose: string;
dataSource: {
collection: "supportTickets" | "customers" | "slaPolicies";
fields: string[];
};
interactions: Array<{
type: "filter" | "sort" | "openDetail" | "createIssue";
label: string;
requiresConfirmation: boolean;
}>;
};
export type UiProposal = {
title: string;
problemStatement: string;
targetRoute: "/admin/tickets" | "/admin/customers";
status: UiProposalStatus;
components: UiProposalComponent[];
reviewNotes: string[];
};
ここで大事なのは、kind と dataSource.collection を狭くしていることです。AIが「便利そうだから」と未知の部品や未知のデータを提案しても、アプリ側の型とバリデーションで止められます。
ハンズオン2: Firestoreへ提案を保存する
次に、UI提案を保存するRoute Handlerを作ります。ここではAI APIの呼び出しは扱いません。ChatGPTやCodexで作った仕様案、または社内ツールから生成した仕様案を、レビュー台帳へ登録する入口です。
// src/app/api/ui-proposals/route.ts
import { FieldValue } from "firebase-admin/firestore";
import { NextRequest, NextResponse } from "next/server";
import { adminDb } from "@/lib/firebase/admin";
import type { UiProposal } from "@/types/uiProposal";
const allowedKinds = new Set(["metricCard", "filterTabs", "dataTable", "actionPanel"]);
function validateProposal(input: UiProposal) {
if (!input.title || !input.problemStatement) {
return "title and problemStatement are required";
}
if (!["/admin/tickets", "/admin/customers"].includes(input.targetRoute)) {
return "targetRoute is not allowed";
}
for (const component of input.components) {
if (!allowedKinds.has(component.kind)) {
return `component kind is not allowed: ${component.kind}`;
}
if (component.interactions.some((item) => item.type === "createIssue" && !item.requiresConfirmation)) {
return "createIssue interaction requires confirmation";
}
}
return null;
}
export async function POST(request: NextRequest) {
const proposal = (await request.json()) as UiProposal;
const validationError = validateProposal(proposal);
if (validationError) {
return NextResponse.json({ error: validationError }, { status: 400 });
}
const docRef = await adminDb.collection("uiProposals").add({
...proposal,
status: "draft",
source: "ai_assisted",
createdAt: FieldValue.serverTimestamp(),
updatedAt: FieldValue.serverTimestamp(),
});
return NextResponse.json({ proposalId: docRef.id });
}
この時点ではまだ実装しません。PanelDeskでは、draft の提案を管理者が確認し、採用する場合だけGitHub Issueへ起票します。
ハンズオン3: レビュー観点を固定する
AIがUIを提案できるようになるほど、レビュー観点を毎回思い出す運用は破綻しやすくなります。そこで、Firestoreに保存する前後で、同じチェックリストを使います。
// src/lib/uiProposal/reviewChecklist.ts
export const uiProposalReviewChecklist = [
{
id: "data-minimization",
label: "画面に表示する個人情報が必要最小限か",
required: true,
},
{
id: "permission-boundary",
label: "権限ごとに見える操作が分かれているか",
required: true,
},
{
id: "destructive-action",
label: "破壊的操作に確認ステップがあるか",
required: true,
},
{
id: "accessibility",
label: "キーボード操作とラベルが成立するか",
required: true,
},
{
id: "design-system",
label: "既存のTailwindコンポーネントで表現できるか",
required: false,
},
] as const;
レビューコメントも uiProposals/{proposalId}/reviews のサブコレクションに残します。
await adminDb
.collection("uiProposals")
.doc(proposalId)
.collection("reviews")
.add({
reviewerId: currentUser.uid,
checklistResults: {
"data-minimization": true,
"permission-boundary": true,
"destructive-action": false,
accessibility: true,
"design-system": true,
},
comment: "GitHub Issue作成ボタンに確認モーダルが必要です。",
createdAt: FieldValue.serverTimestamp(),
});
この形にしておくと、「AIが出したUIが良かったか」だけでなく、「どの観点で差し戻したか」を後から集計できます。たとえば、AI提案の7割がアクセシビリティで差し戻されるなら、プロンプトや社内テンプレートを改善する判断材料になります。
ハンズオン4: GitHub Issueへ渡す文面を作る
承認された提案は、GitHub Issueへ手で転記するのではなく、実装チケットの本文に変換します。ここではGitHub API呼び出しの詳細には踏み込まず、Issue本文の生成だけに絞ります。
import type { UiProposal } from "@/types/uiProposal";
export function buildUiProposalIssueBody(proposal: UiProposal) {
const components = proposal.components
.map(
(component) =>
`- ${component.title}: ${component.kind}\n` +
` - purpose: ${component.purpose}\n` +
` - data: ${component.dataSource.collection} (${component.dataSource.fields.join(", ")})`,
)
.join("\n");
return [
"## 背景",
proposal.problemStatement,
"",
"## 対象ルート",
proposal.targetRoute,
"",
"## 実装するUI部品",
components,
"",
"## 受け入れ基準",
"- Firestore Security Rulesと画面側の権限表示が一致している",
"- 破壊的操作には確認ステップがある",
"- キーボード操作とaria-labelを確認している",
"- 既存のTailwind設計から外れた装飾を増やしていない",
].join("\n");
}
AIが作った「きれいな画面案」を、開発者が実装できる粒度へ落とすには、この変換が効きます。UIの見た目だけでなく、データソース、操作、権限、完了条件までIssueに含めると、実装レビューがぶれにくくなります。
実務での注意点
Intelligent UIの発表は、ユーザーごとにUIが変わる未来を強く感じさせます。一方で、業務アプリでは「毎回違う画面」が必ずしも正義ではありません。問い合わせ対応、経理、勤怠、顧客管理のような反復業務では、同じ場所に同じ操作がある安心感も重要です。
そのため、まずは次のような領域から始めるのがおすすめです。
| 向いている領域 | 理由 |
|---|---|
| 管理画面の改善案 | 社内レビューを通しやすく、影響範囲を限定できる |
| ダッシュボードの並び替え案 | データ表示中心で、破壊的操作が少ない |
| FAQやオンボーディング | 説明と小さな操作の組み合わせが効果的 |
| 問い合わせの一次対応画面 | Firestoreに判断ログを残しやすい |
逆に、支払い、契約変更、ユーザー削除、外部送信を伴うUIは、AI提案を直接操作に結びつけない方が安全です。提案、レビュー、実装、検証の段階を分けてください。
まとめ
GPT-6 Intelligent UIは、AIが「答えを書く」だけでなく、「操作できる体験をその場で構成する」方向を示した発表です。Web系エンジニアにとって重要なのは、その体験をそのまま真似することではなく、生成されたUI案をプロダクト開発のワークフローへどう接続するかです。
PanelDeskの例では、AIの提案を型付き仕様にし、Firestoreへ保存し、レビュー観点を固定し、承認後にGitHub Issueへ変換する流れを作りました。これなら、AIによるUI発想の速さを活かしつつ、Next.js + Firestoreの実務で必要な監査性と再現性を保てます。
まずは本番画面を自動生成するより、社内管理画面の改善提案を1つ uiProposals に保存するところから始めるのが現実的です。AIが画面を組み立てる時代ほど、人間がどこで承認したかを残す設計が効いてきます。