AIエディタ(Cursor)を使って3日で英語学習アプリを作り、App Store にリリースした話【詳細編】
この記事について
第1編では、きっかけからリリースまでの流れを書きました。ここでは 機能仕様、画面の作り方(Stitch × Cursor)、データと音声、開発中に足した便利機能、技術の骨組みを整理します。
アプリはこちらからダウンロード(無料)
機能仕様(アプリがやっていること)
コンテンツの3種類
英作文 / フレーズ / 単語の3種別です。いずれも「日本語テキスト・英語テキスト」のペアで持ち、同じ UI の型(モード・向き・順序)で回します。
学習モード(各種別共通で2つ)
聞き流し
プロンプト言語 → 解答言語の順で 音声を連続再生(日英なら「日本語 → 英語」)。画面には現在の文を表示します。
出題順は「カテゴリー順」か「ランダム(セッション内でシャッフル)」です。フラッシュカード
表面は プロンプト側だけ。タップで解答表示。右スワイプ=正解、左スワイプ=不正解として記録します。
言語の向き(2択)
向き表面裏面聞き流しの再生順日英日本語英語日本語 → 英語英日英語日本語英語 → 日本語
カテゴリー
学習開始前に 特定のカテゴリーだけ、または すべてを選べます。種別によって中身がないカテゴリーは、画面に出さないなどの調整も入れています。

デザイン:Cursor → Stitch → Cursor
最初から完成度の高い画面を Cursor に書かせるのは難しいので、次の 往復にしました。
Cursor で、まず 動く画面を SwiftUI で作る(シミュレータで確認)。
その画面の スクリーンショットを取る。
Stitch(Google の UI 向けツール)に渡し、レイアウト・タイポ・余白・トーンを整えた案を得る。
その意図を プロンプトや画像付きで Cursor に戻し、SwiftUI のコードへ反映してもらう。
「動く実物」を起点にするので、「ここが狭い」「ここをもっと静かに」といった調整を、デザイナーでなくても会話で進めやすいです。
色やコントラストは、実装側で DesignTokens(例: 背景 #0e0e10、アクセントに近い #a1cddd など)にまとめ、Stitch で決めたトーンと揃えやすくしています。
音声:Azure Speech で一括生成
品質とコストのバランスから、読み上げには Microsoft Azure Speech(Text to Speech) を使いました。Neural 音声で自然さを確保しつつ、商用の枠組みの中で運用しやすい、という判断です。
運用のイメージは次のとおりです。
Excel(またはそれを元にしたコンテンツ一覧) を起点に、日本語・英語のテキストを整理する
開発用スクリプトで API キーとリージョンを環境変数で渡すだけで、2000 を超える本数の MP3 をまとめて生成できる
各ファイルは locale | voice | テキスト をハッシュした ID(ファイル名) と対応づけ、アプリに同梱する JSON(各問題の ID) と 同じルールで紐づくので、「どの文のどの言語の音声か」が一貫して管理できる
文言を差し替えたときも、同じ規則で再生成・差し替えしやすく、本数が増えても破綻しにくい形にしています。
開発中に足した「あると便利」な機能
実機やシミュレータで触りながら、自分が続けたくなるかを基準に、次を追加しました。
フラッシュカード:間違いだけ再挑戦
1 周終了後、不正解だった問題だけでもう一度まわせます。結果画面から「間違いだけ再挑戦」で、抜けに集中できます。
聞き流し:一巡で終了か、繰り返しか
セッション設定で選べます。
一巡で終了 … 選んだ範囲を最後まで流したら停止
繰り返し … 最後まで行ったら先頭に戻ってループ
通勤などの長さに合わせて切り替えられます。
学習履歴が見えること
ホームなどで、学習の積み重ねが数字で見えるようにしました(合計学習日数・連続学習日数、英作文まわりの進み具合など)。積み上がりが、そのまま モチベーションの確認につながるように意識しました。
技術スタックとプロジェクトの骨格
項目内容言語・UISwift / SwiftUIIDEXcodeAI エディタCursor(リポジトリ全体をコンテキストに開発)学習コンテンツアプリバンドル内の JSON(カテゴリー定義+問題リスト)音声同梱 MP3(オフライン再生。上記 ID 規則で JSON と対応)データ永続化(例)SwiftData で進捗・学習日などを端末内に保存
フォルダ構成のイメージ(抜粋)
App/ … 起動、デザイントークン、広告・分析の初期化など
Data/ … JSON の読み込み、モデル、進捗の読み書き
Features/ … ホーム、セッション設定、聞き流し、フラッシュカード、設定など画面単位
Services/ … 音声の連続再生、同梱音声の解決、TTS 周りの設定など
Resources/ … JSON、MP3、カテゴリー用画像など
Cursor には この役割分担を前提に指示すると、変更箇所が迷子になりにくいです。
コンテンツの更新(Excel → JSON)
会議メモや整理済みシートから、Python スクリプトで JSON を生成・更新しています。アプリは ビルド時にバンドルされた JSON を読む形なので、配布アプリがその場でスプレッドシートにアクセスする必要はありません。
ストア運用まわり(任意)
Firebase Analytics … 設定ファイルがあれば初期化(無ければスキップ)
Google AdMob(バナー) … Info.plist のアプリ ID 等と連携
同意(UMP) … 必要に応じて同意フローを先に出してから広告 SDK を動かす流れ
コアの学習体験とは切り離せるので、最初は無しで動かし、あとから足すことも可能です。
Cursor との向き合い方(このプロジェクトでのコツ)
仕様の一文(社内メモや CONCEPT のようなドキュメント)をリポジトリに置き、「ここを正」と言い切る
変更は ファイルパスを指定して依頼する(例: 特定の View だけ直して、など)
Stitch のあとは スクショ+トーンの指示と DesignTokens の更新をセットで頼むと、見た目と実装のズレが減る
音声は **「Swift と生成スクリプトで ID 規則を同一」**に固定する
おわりに
第2編では、機能、Stitch と Cursor の往復、Azure での一括音声生成と ID 管理、テストしながら足した便利機能、技術の骨組みまでまとめました。
同じやり方で次の作品も組み立てられる、というのが個人的な感触です。第1編と合わせて、誰かの「最初の一歩」の参考になればうれしいです。
