Firebase Studioがすごい！

# はじめに

Googleが以前から提供していた**Project IDX**というクラウドIDXが、Firebaseに統合されて**Firebase Studio**に名前を最近変えました。

少しだけ触ってみたところ「すごい！！」と感じたので、紹介したいと思います。

# Firebase Studioとは

https://idx.google.com

Firebase StudioはクラウドIDEです。クラウドIDEとは、バックエンドをサーバーに置くことによって特殊な環境(モバイル機器や、好きにアプリをインストールできない仕事用のパソコンなど)でもアプリ開発をすることができるというものです。
似たようなものにGitHub codespaceなどがあります。

自分は、「触ってみたいけどパソコンにインストールするのはちょっと...」みたいな技術を見てみるというときに重宝しています。

Firebase StudioはGoogle製LLMのGeminiを最大限活用できるようになっています。ノーコードツールといってもいいほどにコードを書く必要がありません。
(コードを全てAIに任せてしまうことの是非はこの記事の範疇を超えますが...)

# 使い方

https://idx.google.com

上記リンクへアクセスしGoogleアカウントにログイン後、利用規約を確認・了承します。

![IMG_2756.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882850/e9adc112-21a1-4c23-9c78-f3a6bd6a46e0.jpeg)

そうしたら赤枠(↑)の中に、作りたいアプリの仕様について自然言語で書いちゃってください。

そうしたらGeminiがアプリのプロトタイプ作成の提案をしてくれますので、

![IMG_2755.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882850/0e91005a-7f8d-4cd0-b17f-a9a18444c868.jpeg)

:::note
入力が日本語なのにも関わらず、出力は英語になってしまっています。おそらくまだ対応していないのでしょう。
:::

`Prototype this app`をクリックすると、実際にアプリを作ってくれます。
もちろんこの後に、文句を言ってアプリの仕様を変更してもらうこともできます。

時間が結構かかりますが、少し待つと実際に作ったアプリの画面を左に表示してくれます。

![IMG_2757.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882850/0ab4ae16-a978-4968-81a6-70455a778180.jpeg)


エラーのチェックも勝手にしてくれるようです。

# なんかすごい機能

### その1
![IMG_2758.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882850/616a2193-090c-41fd-9e41-71213ea6bf8e.jpeg)

エラーが出ましたが、すぐにGemini側から「エラーを直そうか？」という提案が来ましたので、せっかくなのでエラーを直させてみます。

きちんと直してくれました。素晴らしい！

### その2

今回は使いませんでしたが、Annotate機能を使うとアプリの画面に直接注釈をつけてそれを使ってGeminiに命令ができるようです。

### その3

変更は、勝手にcommitに切り出してくれるようです。gitの機能のおかげでAIが間違って破壊的な変更をしてしまってもすぐに戻すことができます。

![IMG_2760.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882850/a017f85e-17f1-4aeb-b15e-150c408bbf58.jpeg)

### その4

満足のいくアプリが出来上がったら、Firebaseへのデプロイも自動的にしてもらうこともできるようです。だからFirebase Studioなんですね！

# さいごに

最後にFirebase Studioを使ってほとんどコードを書かずに(0ではないです)実用性のあるアプリを作成することができましたので、紹介させてください。


https://words-cli.sonneko.com

CLI風のインターフェースで英単語を覚えることができるというしょーもないPWAアプリです。

ソースはGitHubにあります。

https://github.com/sonneko/memorizing-words-tool-by-ai

スターつけてくれると嬉しいです。(僕が書いたコードではありませんが...)

# 参考

<details><summary>このアプリを作成するとき、Geminiに提供したプロンプト(Gemini生成)</summary>


```text
**開発依頼: オフライン対応 PWA CLI風単語学習アプリケーション**

**概要:**
React と TypeScript を使用し、提供される JSON 形式の単語データに基づいた、オフラインファーストの Progressive Web App (PWA) を開発してください。ユーザーインターフェースは CLI (コマンドラインインターフェース) 風の見た目と操作感を**厳密に再現**するものとします。

**技術スタック:**
* フロントエンド: React (Client-Side Rendering), TypeScript
* 永続化: ブラウザ標準API (IndexedDB)
* オフライン/PWA機能: ブラウザ標準API (Service Worker, Web Manifest)
* その他使用技術: Fetch API (データ読み込み), CLI風UIライブラリ (任意だが推奨)

**データソース:**

1.  **主単語リスト:**
    * ファイル: `vocab.json`
    * 形式: JSON配列。各要素は `{"ja": "日本語訳", "en": "英単語"}` の構造を持つオブジェクトです。`ja` には `；` または `，` 区切りで複数の意味、`()` で補足情報が含まれる場合があります。`en` は単一の英単語です。
    * 提供方法: PWAの配布物としてアプリにバンドルします。アプリ起動時に一度読み込み、メモリ上で扱います。
2.  **間違えた単語リスト:**
    * 保存先: ブラウザの **IndexedDB**。
    * 管理方法: ユーザーが指定する「テスト名」をキーとして、リスト `[{"ja": "...", "en": "..."}]` を保存します。
    * 要件: 同じ `en` フィールドを持つ単語はリスト内で重複させません。

**ユーザーインターフェース (CLI風GUI):**

* **見た目:** ターミナルやコンソールを模した、単色の背景と文字色によるCLI風のデザインを再現します。
* **構成:** アプリケーション画面は、メッセージや出力が表示されるスクロール可能な**出力エリア**と、ユーザーがコマンドや応答を入力する画面下部の**単一入力エリア**で構成されます。
* **操作感 (厳密なCLI操作):**
    * アプリケーション起動時または各モード終了後、メインメニューが番号付きリストとして出力エリアに表示されます。ユーザーは入力エリアに**番号**を入力してモードを選択します。
    * 各モード開始後の詳細入力（学習範囲、レビューテスト名、検索語句など）は、システムが出力エリアに**問いかけ（プロンプト）を表示**し、ユーザーが入力エリアに**その応答を入力する対話形式**で行います。
    * 学習中・レビュー中は入力エリアは基本的に**解答用**として機能します。
    * 学習中・レビュー中に `q` と入力すると、セッションを中断し、そこまでの結果を表示してメニューに戻ります。

**機能要件:**

1.  **アプリケーション起動とデータ読み込み:**
    * アプリ起動時に、バンドルされた `vocab.json` をフェッチし、メモリに読み込みます。
    * 読み込み成功後、単語数とメインメニューを出力エリアに表示します。
    * 読み込み失敗時は、エラーメッセージを出力エリアに表示し、アプリが使用できない状態であることを示します。
2.  **学習セッション (メニュー番号 `1`):**
    * メインメニューで `1` 入力後、対話形式で**1始まり**のインデックス範囲（例: `1-100`）を入力させます。入力検証を行い、無効な場合はエラーメッセージを出力エリアに表示します。
    * 有効な範囲入力後、対話形式で学習方向（1: 英語→日本語, 2: 日本語→英語）を入力させます。
    * 範囲指定された単語リストをランダムにシャッフルし、対話形式で順に出題します。
    * 各問題に対し、ユーザーが入力エリアに入力した解答の正誤判定を行います。
    * 不正解の場合は、正解を出力エリアに表示します。
    * セッション中断 (`q` 入力) または全問終了後、そのセッションの正答率を出力エリアに表示します。
    * そのセッションで間違えた単語があれば、対話形式でテスト名を入力させ、後述の「間違えた単語の保存」を行います。
3.  **正誤判定 (`checkAnswer` ロジック):**
    * ユーザー入力と正解の大文字・小文字は区別しません。
    * **英語 → 日本語の場合:**
        * 日本語訳の `()` 内の補足情報を全て無視します。
        * `；` または `，` で分割された複数の訳がある場合、それらは個別の正解候補とみなします。
        * **正規化された日本語訳の** **最初の訳に限り**、その先頭が「に」または「を」で始まる場合、その助詞があってもなくても正解と判定します（例: 訳が「を証明する」なら「を証明する」と「証明する」の両方を正解とする）。
        * 2番目以降の訳については、ユーザー入力と完全に一致した場合のみ正解と判定します。
    * **日本語 → 英語の場合:**
        * 英単語と完全に一致した場合のみ正解と判定します。
4.  **間違えた単語の保存 (学習セッション後):**
    * 学習セッションで間違えた単語エントリのリストを準備します。
    * ユーザーに入力させたテスト名で IndexedDB に保存します。
    * IndexedDB に既に同じテスト名のリストが存在する場合、既存リストと今回のリストを結合し、`en` フィールドを基に重複を排除したユニークなリストを作成して上書き保存します。
    * 保存完了メッセージを出力エリアに表示します。
5.  **間違えた単語レビュー (メニュー番号 `2`):**
    * メインメニューで `2` 入力後、対話形式でレビューしたいテスト名を入力させます。
    * IndexedDB から該当するテスト名のリストを読み込みます。リストが見つからない、または空の場合はメッセージを出力エリアに表示し、メニューに戻ります。
    * 読み込んだ単語リストをランダムにシャッフルし、対話形式で順に出題します。
    * 解答の正誤判定ロジックは学習セッションと同じです。
    * レビュー中に**正解**した単語は、セッション終了後に IndexedDB 上のリストから**削除**します。セッション中に間違えた単語のみを残したリストを作成します。
    * セッション中断 (`q` 入力) または全問終了後、そのセッションの正答率を出力エリアに表示します。
    * セッション終了後、更新された（正解した単語が削除された）リストを IndexedDB に上書き保存し、更新メッセージを出力エリアに表示します。
6.  **単語検索 (メニュー番号 `3`):**
    * メインメニューで `3` 入力後、対話形式で検索したい語句を入力させます。
    * メモリ上の全単語リストに対し、英単語 (`en`) と日本語訳 (`ja`) の両方から、大文字小文字を区別しない部分一致で検索します。
    * 検索結果をリスト形式で出力エリアに表示します（日本語訳は `vocab.json` のオリジナル文字列を使用）。
    * 検索結果表示後、Enterキーなどの任意の入力を待ってからメニューに戻ります。
7.  **正答率表示:**
    * 学習セッションおよび間違えた単語レビューセッションの終了時に、そのセッション単位の正答率（正解数/問題数 (%)）を出力エリアに表示します。
8.  **終了 (メニュー番号 `4`):**
    * メインメニューで `4` 入力後、終了メッセージを出力エリアに表示します。PWAはブラウザタブが閉じられるまで存続します。

**PWA要件:**

* Service Worker を実装し、アプリケーションの主要アセット (`index.html`, バンドルJS/CSS, `vocab.json` など) をキャッシュすることで、**オフライン時でもアプリケーションが使用可能**であること。
* Web Manifest ファイルを定義し、ホーム画面への追加（インストール）に対応していること。

**エラーハンドリング:**
* 無効なユーザー入力（メニュー番号外、範囲形式エラー、テスト名未入力、検索語句未入力など）、データ処理エラー（IndexedDBエラーなど）が発生した場合は、出力エリアにエラーメッセージや適切な指示を表示し、ユーザーが操作を続けられるようにします（アプリの強制終了はしません）。

```
</details>