🤖

【GAS】完全オフライン対応&SPA。高3の私が「最強の単語帳」をClaude Opus 4.1と自作した話

に公開

こんにちは、高校3年生で受験生の あるひと です

受験勉強において「英単語の暗記」は避けて通れません。世の中にはAnkiやmikanなどの素晴らしいアプリがありますが、「自分が間違えた単語だけを、自分のスプレッドシートで管理し、かつ爆速で回したい」というニッチかつ切実な要望を完全に満たすものは見つかりませんでした。

「なければ作ればいい」の精神で、Google Apps Script (GAS) をバックエンドにしたWebアプリを開発しました。

ただし、ただのGASアプリではありません。GAS特有の「もっさり感」を克服するため、SPA(Single Page Application)構成と徹底した非同期処理を取り入れ、ネイティブアプリ並みのレスポンスを実現しました。

また、本開発では Gemini 2.5 Pro と Claude Opus 4.1 という最新AIモデルを「適材適所」で組み合わせることで、受験勉強の合間という限られた時間での爆速開発を実現しました。

デモと機能紹介

まずは動作をご覧ください。回答時のラグはゼロです。

アプリの主な特徴

体感レイテンシー・ゼロ: 回答データの送信完了を待たずに次の問題を表示する「Optimistic UI(楽観的UI)」を採用しています。

オフライン完全対応: 地下鉄でも通信制限中でも学習可能です。オフライン時のデータはLocalStorageに保存され、復帰時に自動同期されます。

自動セットアップ: スプレッドシートの準備はシート名を変えるだけ。ヘッダー等の構築はスクリプトが自動で行います。

細部へのこだわり: ダークモード対応、音声読み上げのガベージコレクション対策など、実用性を重視しました。

技術選定とアーキテクチャ

「受験生はお金がないが、Googleアカウントは持っている」という制約から、サーバー代無料のGAS + Google Sheets構成を選択しました。

しかし、GASの google.script.run は呼び出しから完了までに数秒のレイテンシーが発生することがあります。1分1秒を惜しむ受験生にとって、回答のたびにローディングが入るのは致命的です。

そこで、以下のアーキテクチャを採用しました。

システム全体のアーキテクチャ

データフローの詳細

Optimistic UIの仕組み

オフライン対応の実装

キャッシュ戦略

「Read Heavy, Write Async」戦略

通常のGASアプリは、処理の完了を待って(withSuccessHandler)から画面を更新しますが、今回はそれをあえて無視する戦略を取りました。

初回起動時: google.script.run で単語データと統計データを**「全件取得」**し、メモリとLocalStorageにキャッシュします。

回答時(Write):

  • 即座に次の問題を表示(UI更新)
  • 裏側で google.script.run を投げっぱなしにする(Fire-and-forget)
  • もし通信失敗しても、LocalStorage上のキュー(Pending Results)に保存されるためデータは失われません

これにより、サーバーとの通信中であっても、ユーザーはラグなしで次の問題を解き進めることができます。

Vanilla JSによるSPA構成

学習コストとオーバーヘッドを抑えるため、ReactやVueはあえて採用せず、**Vanilla JS(フレームワークなしの純粋なJavaScript)**で実装しました。

GASの HtmlService 上で動作するため、バンドルツールを使わずに Index.html 内で完結させる必要があったことと、「DOM操作の基礎を理解したい」という意図もありました。

🤖 開発フロー:最新AIモデルの「適材適所」オーケストレーション

本アプリのコードは、私が1行ずつ手打ちしたものではありません。私は**「プロダクトマネージャー兼アーキテクト」に徹し、コーディングは2025年現在の最新AIモデルたちに任せました。**

それぞれのモデルの特性を理解し、以下のようなサイクルを回して開発を行いました。

役割分担

Gemini 2.5 Pro (Deep Research): 【リサーチャー・企画】

アイデアの壁打ち、実現可能性の検証、UI/UXの提案を担当。
Deep Researchによる深い文脈理解で、複雑な要件定義を投げても破綻しませんでした。

Perplexity: 【情報収集】

最新のGASの仕様変更や、ニッチなライブラリのドキュメント検索に利用。

Claude Opus 4.1 (Artifacts): 【実装エンジニア】

ここが開発の核でした。企画書を渡すと、3000行を超えるSPAの全コードを一発で、しかもバグ無しで書き上げました。
特に「Artifacts」機能で、プレビューを見ながらファイルごとにコードを整理してくれる能力は圧倒的です。

Gemini 2.5 Pro: 【コードレビュー・デバッガー】

Claudeが書いたコードのセカンドオピニオンとして利用。デプロイ時のエラーログ解析など、多角的な視点でのチェックに活用。

なぜ「Opus 4.1」をメイン実装にしたか

しかし、同じ要件定義書を Claude Opus 4.1 に渡したところ、3000行を超えるコードを一発で、バグ一つなく書き上げました。

「Geminiで要件を詰め、Opus 4.1で実装し、Geminiでレビューする」。このモデル間連携こそが、個人開発を爆速化させる鍵だと確信しました。

実装の推しポイント

🛠 オフライン検知と同期ロジック

一番苦労したのは「電波が悪い場所でも勉強したい」という要件の実装です。navigator.onLine を監視し、オフライン時は送信キューにデータをスタックさせます。

オンラインに復帰したイベント(window.addEventListener('online', ...))をフックし、裏側で再送処理を走らせることで、ユーザーは通信環境を意識せずに学習を続けられます。

🛠 音声読み上げのガベージコレクション対策

Web Speech APIの実装において、音声が途中で途切れるバグに悩まされました。調査の結果、ブラウザのガベージコレクションが再生中のオブジェクトを破棄してしまうことが原因だと判明しました。

これに対し、再生オブジェクトをグローバル変数に保持し、再生終了イベントまで明示的に維持することで解決しました。

🛠 開発環境のモダン化 (clasp + Git)

GASのエディタはブラウザ上でも動きますが、バージョン管理ができないのが欠点です。今回は @google/clasp を導入し、VS Codeで開発 → Gitで管理 → コマンド一発でデプロイ、というフローを構築しました。

# claspでデプロイ
clasp push
clasp deploy

📦 スプレッドシートのセットアップ(DXへの配慮)

このアプリのバックエンドはGoogleスプレッドシートですが、ユーザーに面倒な設定を強いないよう工夫しました。

本来なら「A列にIDを入れて、B列に英語を...」と細かく設定する必要がありますが、本アプリはオートセットアップ機能を搭載しています。

オートセットアップの流れ
  1. シート名の変更: 新規スプレッドシートを作成し、シート名を「単語リスト」に変更する
  2. アプリにアクセス: デプロイしたWebアプリを開くと、スクリプトが自動的に必要なヘッダー行(WordID, English, Japanese...)やログシートを生成します
  3. 単語データの入力: あとは生成された列に単語を入力するだけです

「シート名の変更」と「単語のコピペ」だけで使い始められる。ここまでやって初めて「使えるツール」になると考え実装しました。

開発を終えて

「車輪の再発明」だとしても

正直、既存のアプリを使えば早かったかもしれません。しかし、「自分の欲しい機能を、最新のAI技術を駆使して実現する」という経験は、単語を100個覚える以上に価値があったと感じています。

特に、非同期処理やキャッシュの概念は、実際にユーザー(自分)が「遅い!」とイライラする体験があったからこそ、深く理解できました。

今後の展望

受験まで残り時間は少ないですが、このアプリを使って英単語ターゲット1900を完走します。

無事大学に合格したら、次はPWA化してホーム画面からネイティブアプリのように起動できるようにしたり、Reactの導入に挑戦してみたいです。

もしコードに興味がある方は、GitHubを覗いてみてください。❤をいただけると、受験勉強の励みになります!

Discussion