Q
PRODUCT NOTE / PRD
Quick Query Question
ページを閉じずに、その場で AI に訊く。
この文書は「どう使うか」ではなく、なぜ・誰のために・どんな判断で作ったかを記録した開発ノートです。
TL;DR
ひとことで
Quick Query Question は、ブラウザのサイドパネルに常駐する AI アシスタントです。閲覧中のページから離れずに、引用テキスト・画面キャプチャ・各種ファイル(PDF・画像・動画・CSV・テキスト等)を添えて質問・翻訳・校正・要約ができます。バックエンドは nzw.jp(Gemini)で、利用は許可制です。
Problem
背景・解きたい課題
v2.0.0 以前の動機は当時の設計文書が残っていないため、コミット履歴と実装から再構成した。v1 系の背景は推測
- 「AI に訊くたびにページを離れる」摩擦 — 調べ物や文章作業の途中で別タブの AI に移動すると、作業文脈が途切れる。往復のコストが積み重なる。
- ポップアップは閉じると消える — 初代(v1 系)はポップアップ UI だった。ページをクリックした瞬間に閉じてしまい、「ページを見ながら会話する」用途に構造的に向いていなかった。
- 手元の材料を渡すのが面倒 — 参照したい文章・画面・資料が目の前にあるのに、コピペやアップロードの手間が挟まる。
- よく使う指示を毎回打ち直している — 「日本語に翻訳」「敬語に直す」など、繰り返す指示が定型化していた。
Who
ターゲットユーザー
プライマリ
運営者本人と、許可リストに登録された知人。Google 認証を通ったユーザーのみが利用でき、一般公開は前提にしていない。
主なユースケース
- 読んでいる記事の一節を引用して要約・翻訳
- 操作に迷った画面をキャプチャして「これは何?」
- PDF や CSV を添付して中身を確認・整理
- メールや資料の下書きを校正・敬語化
Solution & Scope
解決策とスコープ
コア機能(In scope)
- サイドパネル常駐チャット(履歴保存・続きから再開)
- ページのテキストを「引用する」ボタンで取り込み
- 表示中の画面をキャプチャして添付
- ファイル添付(PDF・画像・動画・CSV・テキスト・XML 等)とドラッグ&ドロップ
- 長文入力の自動ファイル化
- プロンプト登録(1〜50 個)とワンタップ挿入
- Markdown 整形表示とワンクリックコピー
やらないこと(Non-goals)
- 一般公開・誰でも使える AI サービス化
- ページ内容の常時収集・バックグラウンド送信
- Chrome 以外のブラウザ対応
- 拡張内での独自 AI モデル保持
Success Metrics
成功指標(KPI)
「ページを離れずに完結したか」を中心に見る。数値は目標仮置き
< 3 操作
選択から質問送信まで
(材料を渡す手間)
Decision Log
主要な意思決定ログ
v2.0.1 以降の項目は実作業に基づく記録。v2.0.0 以前および security / UX の項目は、実装から読み取れる判断を再構成したもの。一部は実装から再構成
v2.0.2 「常に出す」に条件を一つ足す — 使えない相手にはボタンを出さない
- DECISION
- v2.0.1 で「引用ボタンはパネルの開閉に関わらず常に出す」と決めたが、未認証のときは設定に関わらず出さないという条件を足した。ログアウトした瞬間、すでに表示中のボタンも消す。判定は content script が保存済みユーザー情報の有効期限(
exp)だけを見て行い、JWT 本体は読まない。認証状態が読み取れるまでは OFF 扱いにする。あわせて引用ボタンの表示 ON/OFF を設定画面に出した(即時反映)。
- WHY / 仮説
- この拡張は許可リスト制で、未ログインのままでは押しても何も起きない。押して無反応なボタンは「機能がある」ではなく「壊れている」と読まれる。加えて拡張はあらゆるページに注入されるため、権限のない相手にまで UI を撒くこと自体が無駄でもある。判定を content script 側で完結させたのは、ページごとに背景へ問い合わせる往復を避けるため。ただしページ側のコードに認証情報の中身を持ち込まないのは譲れないので、読むのは有効期限だけに絞った。読めない・判断がつかない状態は「出さない」側へ倒す(fail-closed)。
- RESULT
- 未ログインおよびログアウト直後のページから引用ボタンが消えた。ログイン済みでも邪魔な場合は設定で切れるようになり、「常に出す」の押しつけも同時に解消した。
v2.0.2 入力欄は伸ばさず、最初から 5 行ぶん空けておく
- DECISION
- サイドパネルの入力欄を、常に 5 行分(116px)の高さで確保するようにした。CSS の
min-height と JS 側の定数の両方に同じ値を持たせている。
- WHY / 仮説
- 1 行から伸びる入力欄は短文の投稿を前提とした形だが、この拡張の主用途は「引用やファイルを添えて長めに指示する」ほう。書いている途中で欄が伸びるたびにレイアウトが動き、直前に書いた文が視界の外へ押し出される。最初から広く取っておけば、入力中に高さが変わらない。
- RESULT
- 書き始めから 5 行が見える状態になり、入力中の高さ変化がなくなった。値を 2 箇所に持たせた点は重複であり、片方だけ変えると崩れる。次に触るときに一元化する。
v2.0.0 ポップアップを捨て、サイドパネル常駐にする
- DECISION
- v1 系のポップアップ UI を全面的に廃し、
chrome.sidePanel による常駐パネルへ作り直した。同時に AI 基盤を ChatGPT 直叩きから nzw.jp(Gemini)経由へ移した。
- WHY / 仮説
- ポップアップは「ページをクリックすると閉じる」という仕様上、ページを見ながらの会話が原理的に成立しない。UI の改善では埋まらない構造的な問題だと判断した。バックエンドを自前に寄せたのは、API キーを拡張に埋め込まず許可制にできるため。
- RESULT
- ページを見ながら会話が続けられるようになり、会話履歴の保存・再開も自然に組み込めた。
UX 材料を渡す起点は「ページ側」に置く
- DECISION
- テキストを選択すると、その場に「引用する」ボタンを出す方式にした。パネル側から選択テキストを取りに行く方式は採らない。
- WHY / 仮説
- 「選択 → パネルへ視線を移動 → ボタンを押す」より、「選択 → その場で押す」ほうが視線移動も操作数も少ない。ユーザーの意識がある場所に操作を置くべきだと考えた。
- RESULT
- 引用は選択直後の 1 クリックで完了。のちに「範囲添付」ボタンと役割が重複していることが判明し、統廃合の判断につながった(下記)。
v2.0.1 重複していた「範囲添付」を捨て、ファイル添付に置き換える
- DECISION
- 選択テキストを添付する「範囲添付」ボタンを廃止し、その枠をファイル添付に置き換えた。画像は既存の
images 経路、それ以外は新設の files 経路(base64 + mime_type)で送る 2 系統に分けた。
- WHY / 仮説
- 引用ボタンと範囲添付は「選択テキストを渡す」という同じ仕事をしており、ボタンが 2 つあること自体が迷いを生んでいた。機能を足すより先に、重複を消して枠を空けるべきだと判断した。経路を分けたのは、画像は送信前の縮小が必要で、他形式とは前処理が異なるため。
- RESULT
- 操作の意味が「テキストは引用/実体のあるものは添付」と一意になった。PDF・動画・CSV 等は Gemini の inline データとして送られる。バックエンド反映待ち
UX 長文はユーザーに意識させず自動でファイル化する
- DECISION
- 入力欄の内容が 2000 文字を超えた場合、送信時に自動で
.txt の添付へ切り出す。
- WHY / 仮説
- 長文をそのまま本文に載せると入力欄が読みにくくなる。かといって「長いので自分でファイルにしてください」と要求するのは本末転倒で、機械が判断できることは機械がやるべきだと考えた。
- RESULT
- ユーザーは長さを気にせず貼り付けられる。入力欄も添付一覧も見通しが保たれる。
v2.0.1 引用ボタンをパネル未起動でも押せるようにする
- DECISION
- 従来はサイドパネルを開いている間しか引用ボタンを表示していなかったが、開閉に関わらず常に表示し、閉じている状態で押された場合はパネルを開いてから引用を挿入する方式に変えた。
- WHY / 仮説
- 「引用したい」と思った瞬間にボタンが無いのは、機能が無いのと同じ。先にパネルを開かせるのは、こちらの都合をユーザーに押し付けている。
- RESULT
- 実装上の落とし穴があった。
chrome.sidePanel.open() はユーザー操作の直後にしか呼べないため、await を挟んでから呼ぶとジェスチャが失効して拒否される。引用テキストの保存より先に open() を呼ぶ順序が必須で、ここを崩すと機能が壊れる。
security API キーを拡張に持たせず、許可制の自前 JWT を挟む
- DECISION
- Google の
id_token を nzw.jp のバックエンドで検証し、自前 JWT に交換して /v1/assistant/* を呼ぶ。許可リストに載ったメールアドレスのみ通す。
- WHY / 仮説
- 拡張機能のコードはユーザーが閲覧できるため、AI の API キーを同梱すれば実質公開と同じになる。鍵はサーバー側にのみ置くべきだと判断した。
- RESULT
- 鍵を露出させずに配布でき、利用者と利用量をサーバー側で制御できる。反面、ストアでは限定公開が前提になった。
privacy 権限は使わなくなった時点で削る
- DECISION
- 範囲添付の廃止に伴い、選択テキスト取得のためだけに使っていた
scripting 権限を manifest から削除した。
- WHY / 仮説
- 使っていない権限が残っていると、審査で説明できないうえ、ユーザーに不要な不安を与える。権限は機能と一対一で増減させるべき。
- RESULT
- 要求権限が 1 つ減り、機能と権限の対応が説明可能な状態に保たれた。
Architecture
構成メモ
拡張は 3 つのスクリプトに役割を分けている。ネットワーク通信は service worker に集約し、ページ側のスクリプトは最小限に留める。
Milestones
これまでの歩み
v0.5 系2023-09-30初版。ChatGPT 連携のポップアップ型ツールとして公開
v1.0 〜 v1.22023-10 〜 2024-01入力上限の緩和、右クリックメニュー、コピー・テキスト書き出しなどを追加
v2.0.02026-07-18サイドパネル型へ全面刷新。nzw.jp(Gemini)連携・Google 認証・会話履歴・プロンプト登録・引用ボタン・画面キャプチャ添付に対応
v2.0.12026-07-19範囲添付を廃止しファイル添付(ドラッグ&ドロップ・長文の自動ファイル化)へ置換。引用ボタンをパネル未起動でも利用可能に。scripting 権限を削除
v2.0.22026-08-02未認証時は引用ボタンを表示しない(判定は有効期限のみ・fail-closed)。引用ボタンの表示 ON/OFF を設定に追加。入力欄の高さを常時 5 行ぶん確保
Roadmap / Open Questions
これから
- ファイル添付のバックエンド反映と、実利用での形式ごとの検証。
- 大きなファイルの扱い(inline 送信の上限をどう超えるか)。
- 会話履歴と添付の関係整理(履歴には添付の実体が残らない)。
- ストア掲載バージョンの更新と、限定公開のままでの配布運用。
未決事項:添付データの保持方針、AI 利用コストの上限設計、公開範囲を広げるかどうか。