/typein(タイプイン) という、英語学習とタイピングを組み合わせた無料のWebアプリを公開しました。 絵と日本語と発音と英語を1画面に並べて、意味が分かった状態で英単語を打つという作りです。
- 2026年8月13日 朝9時台:設計開始
- 同日14時台:動くものが公開Preview環境に載る
- 8月15日:独自ドメインで一般公開
最終的にコードは4,072行、27コミット、静的42ページ。ゲームモードは5つ、単語は70語、7コースです。 実装はほぼ全部AIがやりました。私が書いたのは指示書だけです。
⚠️ 先に「3日」の中身を正確にしておきます。これは経過日数であって、作業時間ではありません。 しかも私が指示書を書いた時間と、判断に使った時間は計測していません。 つまり「3日で作れた」という数字も、それ自体が何を含んでいるかを言わないと意味を持ちません。 ——これが、まさにこの記事の主題です。
ただ、この記事で書きたいのは「AIすごい」ではありません。この3日間で何度も、 「できている」と示すサインが出ているのに、実際にはできていない場面に遭遇しました。 たとえばこんな場面です。
- テストが通った → でも本番ビルドは落ちていた
- AIの採点が4.0/5.0だった → でも私は見た瞬間に作り直しを決めた
- ドメインが名前解決した → でもDNSは1件も設定できていなかった
- 管理画面が「保存しました」と出た → でもその画面は使われていなかった
(ほかにもあります。全部まとめた一覧は記事の最後に置きました)
AIに任せる範囲が広がるほど、「成功のサインが何を保証しているか」を知っているかどうかが効いてきます。 今日はその話です。
先に現在地を書いておきます。このアプリは 2026年8月15日に一般公開しました (https://typing.sakaki-lifejourney.com)。 ただし公開しただけで、実ユーザー数はまだ計測できておらず、収益はゼロです。 「作れた」「公開できた」「使われる」「稼げる」は別の話で、 この記事で証明できているのは最初の2つまでです。
なぜ英語 × タイピングだったのか
AIを使った副業ポートフォリオとして、3つの仮説を並走させています。その中のWebサービス枠の実験候補として着手しました。
検証したかったのは「作れるか」ではなく、どこまでAIに渡せて、どこから人間が必要になるかです。 題材はなんでもよかったのですが、次の理由で英語タイピングを選びました。
- 検索需要が読みやすい(「英単語 タイピング」のような明確なクエリがある)
- 完全無料+広告で成立させやすい構造
- 既存サービスに穴がありそうだった
3つ目について、AIに競合調査をさせました。日本語圏11サービス、海外10サービス、検索キーワード6件です。
分かったのは、無料の「英語タイピング」自体はたくさんあるものの、 画像・日本語訳・音声・復習設計を全部そろえた無料サービスは、調査範囲では見つからなかったということでした。 それらをそろえているサービスは有料が中心です(月980〜1,580円、月3,300円、2年で29,800円など)。 無料で画像も音声もあるサービスは1つ見つかりましたが、スマホに対応していませんでした。
※ここは「日本語圏に存在しない」ではなく「調査した範囲では確認できなかった」です。 検索順位の調査は米国経由のGoogleだったので参考値ですし、「世界初」と言えるだけの根拠はありません。
中心にあるアイデア:apple ではなく an apple を打たせる
このアプリでいちばんこだわったのは、冠詞を含んだ実際に使う形のまま打たせることです。
学校でも単語帳でも、英単語は apple の形で覚えます。 でも実際に使うときは an apple です。a dog であり、the sun です。 一方で water には冠詞がつかないし、scissors は常に複数形です。
この「単語そのもの」と「実際に使う形」のズレは、あとから直すのがけっこう大変です。 なので最初から an apple を指で打たせる。a / an / the / 無冠詞 / 複数形の5パターンを 全部通るように語彙を選びました(公開時点で70語・7コース)。
タイピングという形式がここで効きます。読むだけだと an は目が滑りますが、 打つときは a と n とスペースを必ず通るからです。手が形を覚える。
将来は単語 → チャンク → 短文と伸ばしていく想定です。
第1幕:作る — 全部グリーンでも、人間が却下することがある
工程を時刻つきで全部出します
まず初日(2026年8月13日)です。時刻はgitのコミット時刻の実測値です。
| 時刻 | 何が終わったか |
|---|---|
| 9:55 | 設計完了(設計書18ファイル・競合調査・広告規約の確認) |
| 11:05 | MVP実装7コミット(エンジン → 語彙 → UI → 5ゲーム → SEOページ → テスト) |
| 14:33〜14:57 | Vercelに公開Preview発行・本番デプロイのロック |
| 15:32 | AIテストで見つかった不具合の修正 |
| 15:41 | 第三者テスト完了の記録 |
| 16:32〜 | UI全面再設計 |
そこから2日かけて本番公開まで行きます。
| 日付 | 何が終わったか |
|---|---|
| 8月14日 | 発音音声70語を作り直して本番公開(この時点ではVercelのURL) |
| 8月15日 | ブランド名を確定し、独自ドメインで一般公開 |
使った技術は Next.js 15 / React 19 / TypeScript / Tailwind CSS、 テストは Vitest(ユニット)と Playwright + axe(E2E・アクセシビリティ)。ホスティングはVercelです。
実装を担当したのは Claude Code、第三者テストとUI再設計を担当したのが Codex でした。
失敗その1:AIが親フォルダごとVercelにアップロードした
順調な話だけ書くとフェアではないので、失敗も出します。
Preview環境を作る作業中、シェルの作業ディレクトリが親フォルダにリセットされた状態でデプロイコマンドが実行され、 副業プロジェクトの事業文書が入ったフォルダごと、2回Vercelにアップロードされました。 やったのはAIです。
結果から言うと、外部への露出はゼロでした。 全デプロイURLにVercelの認証がかかっていたことをAPIで確認しています。見られる状態だったのは自分のチームのメンバーだけで、 存続時間は数分。両方削除して残り0件も確認しました。
ここで大事なのは、これが「AIの判断ミス」ではなく「実行環境の状態」から起きた失敗だということです。 プロンプトをどれだけ丁寧に書いても防げません。防げるのは仕組みだけです。
対策として、デプロイは必ず明示的にフォルダを指定して実行する運用にし、 以後はCLIを使わずGit連携(pushしたら自動でデプロイ)だけにしました。
失敗その2:「Preview」と指定してもProduction扱いになった
もっと怖かったのがこちらです。
Vercel CLIには、Gitに接続していない状態の初回デプロイが「本番」扱いになる挙動がありました。 --target=preview と明示しても効きませんでした。
「preview と指定した」は「preview になった」ではなかったわけです。 この記事の主題が最初に出てきた場面でした。
「気をつける」では絶対にまた事故ります。なので、こうしました。
本番ブランチを、ビルドが通らないロック用ブランチに差し替えた。
本番として指定されているブランチが、そもそもビルドできない中身になっている。 だから本番デプロイは「起きないように注意する」のではなく、構造的に起きない。 このロックは、公開すると決めた8月14日に自分の手で外しました。 それまでは、間違って本番に出したくても出せない状態だったということです。
AIに実装を任せるなら、事故る余地そのものを設定で潰しておく。これは今回いちばん再利用できる学びでした。
AIに自分のアプリをユーザーテストさせた
実装したAIとは別のAI(Codex)に、ソースコードを一切見せずにテスターをやらせました。 URLだけ渡して、実際にプレイして採点させる方式です。
途中で問題が起きました。Codexのサンドボックス環境ではブラウザが起動できなかったのです。 そこでCodexは、未検証の評価をでっち上げることを拒否しました。 仕方がないので、テストの設計・判断・採点はCodex、ブラウザを実際に動かす部分だけをClaude Codeが代行する、 という分業にしました。7ターン、Codex側のトークン消費は約172万です。
結果は 3.9 / 5.0。重大不具合(P0)はゼロ。バグは8件見つかりました。特に痛かったのが3件です。
- 共有ボタンを押すと
http://localhost:3000が本文に入る — 共有された相手には壊れたリンクが届く - 落下ゲームの正確率が、時間切れで落ちた単語を数えていない — 上部の表示だけ100%になる
- 1回ミスしただけの単語が、復習に出てこない — 画面の説明文と実際の挙動が食い違っていた
どれも「動かない」バグではありません。動くけれど、ユーザーの期待とズレている種類の問題です。 自分で作ったものを自分でテストしていたら、たぶん全部見逃していました。
3件とも同日に直して再テストにかけ、全件FIXED・リグレッションなしを確認。評価は 4.0 / 5.0 になりました。
そして、人間が見て却下した
ここからが本題です。
P0ゼロ、4.0/5.0、テストは全部グリーン。数字の上では「完成」に見えます。 それで私は実際に画面を開きました。そして思いました。
これは小学生向けのサイトだ。高校生や大人が開いたら、たぶん恥ずかしい。
ひらがな中心の見出し、大きな丸ボタン、絵文字、原色。「やったね!」に近いトーン。 小学生には親しみやすい。でも私が届けたかったのは、中学生も高校生も大学生も、 英語をやり直したい社会人まで含んだ範囲でした。この見た目では、その人たちは2秒で閉じます。
そこで全面的に方針を変えました。
- 原色・多色・絵文字を減らし、ニュートラルな地色+落ち着いた青系1色に
- 丸文字・巨大な丸ボタン・過剰なカードを抑える
- 幼いコピーをやめる
- 英語を視覚上の主役にする
再設計後、Practice / Falling Words / Speed 60 / Daily Training / Review という表示に変えました。 URLも内部IDも保存キーもそのままなので、記録は引き継がれます。
ここが一番書きたかったこと:AIは指摘していた
「AIは見た目の良し悪しが分からない」という話にしたくなるところですが、事実は違いました。
テストしたCodexは、20項目の評価のうち 「見た目(子供向けすぎないか)」を5点満点の3点と採点し、 「ひらがな・絵文字中心で幼く見える余地がある」とはっきり書いていました。
さらに言えば、実装レポートに載せた人間用レビュー項目にも、 「子ども向けすぎないか」「大人でも使える印象か」という質問が最初から入っていました。
つまり、見落としではありません。指摘は出ていた。それでも直らなかった。なぜか。
それが「バグ」ではなく「方針」だったからです。
共有URLに localhost が混ざるのはバグです。誰が見ても直すべきで、AIは自分で直せます。 でも「小学生向けに見えること」は、それが問題かどうかが、届けたい相手を誰に決めているかで変わる。 小学生専用サービスを作っているなら、あの見た目は正解でした。
だから今回の結論は「AIには分からない」ではなく、こうなります。
AIは問題を指摘できる。どれを問題として扱うかを決めるのが人間の仕事。
言い換えると、AIに渡せないのは能力ではなく優先順位です。 そして4.0/5.0という点数は、「バグがない」ことは保証していても「方針が合っている」ことは保証していませんでした。
幕間:テストが全部通っても、ビルドは壊れる
作り直しを決めたあとの話です。ここから第2幕(公開工程)へ入るのですが、 その前にもう1件、同じ形のズレが出てきたので挟ませてください。
UI再設計のあと、コードを監査して面白いものを見つけました。
再設計の過程で、Next.jsの <Link> が普通の <a> タグに置き換わっていた箇所がありました。結果どうなったか。
- 型チェック(TypeScript): 通る
- ユニットテスト24件: 通る
- 本番ビルド: 失敗
ビルドが落ちるということは、Preview環境にすら出せないということです。 型チェックとテストだけ回して「大丈夫そう」と判断していたら、そのまま気づかずに進んでいました。
「テストが通った」は「壊れていない」ではありません。通した検証の種類の分しか保証されていない。 AIに任せるほど、この差は効いてきます。
もう1件、/daily/ ページの「Best」「Streak」が実データを見ておらず、 記録があるユーザーにも — と表示し続ける状態になっていたのも見つけて直しました。 見た目が整っている分、こういう「それらしく表示されているだけ」は目視だと素通りします。
再設計後の最終状態では、型チェック・Lint・ユニット24件・E2E+アクセシビリティ24件・本番ビルドが全部PASS。 Lighthouseは本番URLの実測でパフォーマンス100・アクセシビリティ100・ベストプラクティス100・SEO100、 LCP 1.5秒・CLS 0 です。
ここまでが「作る」側の話でした。 このズレは、作り終わったあとの公開工程で、さらに立て続けに出てきます。
第2幕:公開する — 「設定できている」ように見えるものが、3回とも違った
📌 ここから先は、ドメイン・DNS・SEOの技術的な話が続きます。 「AIに開発をどこまで任せられるか」だけを読みたい方は、 「いまの正直な現在地」まで飛ばしていただいて大丈夫です。 逆に、自分でドメインを繋いだことがある方には、ここからが本編かもしれません。
ここからが、8月14日〜15日の公開工程です。
正直に言うと、公開作業は「もう作り終わったので、あとは出すだけ」だと思っていました。 実際には、技術的な山場はここに3つありました。しかも3つとも「事前の想定と実態が違った」という同じ形をしています。
罠1:DNSを1件も設定していないのに、もう名前解決していた
公開先は typing.sakaki-lifejourney.com というサブドメインです。 まずは現状確認から、と思って引いてみたら、設定を何もしていないのに、すでに応答が返ってきました。
typing.sakaki-lifejourney.com → 85.131.207.63
zzz-nonexistent-test.sakaki-...com → 85.131.207.63(同じ)
存在しないはずのサブドメインまで、同じIPを返しています。 原因は *.sakaki-lifejourney.com という wildcard(ワイルドカード)Aレコードでした。 定義していないサブドメインを全部まとめて1か所へ向ける設定です。
つまり何が起きていたか。
- ブラウザで開ける → 開ける
digが応答を返す → 返す- でも、実際に届いていた先はレンタルサーバー側で、証明書も別サービスのものだった
「名前解決する」は「設定できている」の証拠になりませんでした。 もしここで「もう繋がってるな」と判断して先に進んでいたら、公開後に 「サイトは開くのに中身が違う」という一番デバッグしづらい状態になっていたはずです。
教訓: wildcardがあるドメインでは、動いているように見えて、実際は別サービスに刺さっている状態が起きる。 判定は「開けるか」ではなく「どこに向いているか」で行う。
罠2:DNSの管理画面が2つあって、片方は使われていなかった
次に、実際にレコードを追加しにいきました。ここで2つ目の罠にはまります。
契約しているXserverには、DNSレコードを編集できる画面が2か所ありました。
| 画面 | そこに表示されるネームサーバー | 実態 |
|---|---|---|
| Xserverアカウント(契約管理)→ ドメイン → DNSレコード設定 | ns1-3.xdomain.ne.jp | 使われていない |
| サーバーパネル → ドメイン → DNSレコード設定 | ns1-5.xserver.jp | こちらが本物 |
最初に開いたのは前者でした。そこにはAレコードもwildcardも表示されていませんでした。 ネームサーバーの情報とSOAだけです。
おかしいと思ったのは、罠1で確認していた実測値と食い違っていたからです。 wildcardが効いているのは分かっているのに、画面には出てこない。
そこで、ドメインが実際にどのネームサーバーを使っているかを確認したところ、 画面に書いてある xdomain.ne.jp ではなく xserver.jp のほうでした。 画面のほうが間違っていたわけです。
怖いのは、どちらの画面で保存しても「保存しました」と表示されることです。 使われていない側に正しいレコードを書いても、成功メッセージは出る。でも何も起きない。
教訓: 「保存された」と「効いている」は別。 判定は管理画面の表示ではなく、外から実際に引いた結果で行う。
最終的に追加したのは、Vercelが提示した値どおり Aレコード1件だけです (typing → 76.76.21.21)。既存のレコードは1つも変更していません。 変更範囲を1件に閉じておけば、うまくいかなかったときに戻す先が明確になりますし、 関係のない機能を巻き込んで壊す事故も起きません。
SSL証明書は、レコード追加から約4分で自動発行されました。
罠3:「このページの正規URLはこれです」の宣言先が、リダイレクトされていた
3つ目は公開直前の点検で見つけた、気づきにくいSEOのバグです。
Webページには canonical(カノニカル)という、 「このページの正規URLはこれです」と検索エンジンに伝えるタグがあります。 それがこうなっていました。
canonical に書いてあるURL : https://.../animals/ ← 末尾にスラッシュあり
実際に /animals/ を開くと : 308 で /animals へ転送 ← 末尾スラッシュなし
自分で「正規URLはこれです」と宣言しておきながら、その宣言先が別のURLへ転送される状態です。 サイトマップも同じ、末尾スラッシュ付きのURLを送っていました。
これも「タグは出力されている」「サイトマップも送れている」という意味では、 すべて正常に動いているように見えます。中身が自己矛盾していただけです。
直し方は2通りありました。
- canonicalとサイトマップの側を、末尾スラッシュなしに書き換える
- サーバーの転送挙動のほうを、すでに宣言してあるcanonicalに合わせる
選んだのは2番です。設定を1行変えるだけで済み、すでに検索エンジンに認識されているURLを 動かさずに解決できるからです。URLを変更するほうは、既存の評価を捨てるリスクがあります。
公開後、7つの経路すべてで「canonicalに書いてあるURL」と「実際に開けるURL」が 一致することを確認しました。
教訓: URLを変えて直すか、挙動を変えて直すか。すでに認識されているURLがあるなら、後者のほうが安い。
おまけの罠:一番早い方法が、一番間違っていた
公開に合わせて、アクセス解析も入れました。ここで指示したのは 「最低限、計測できる状態にしておいて」という、ざっくりしたものです。
このとき一番早い方法は、すでに使っているWordPress用のGoogleアナリティクスの測定IDを、 アプリにもそのまま入れることでした。コピーして貼るだけ、1分で終わります。
でもそれをやると、WordPress側の計測データが汚れます。 別サイトのアクセスが同じ数字に混ざり、どちらの数字も信用できなくなる。
AIは流用せず、アプリ専用のデータ送信先を新しく作りました。
ここは面白いポイントだと思っています。「早くやって」と言われたときに一番早い手段を選ぶと、 あとから戻せない形でデータが壊れるケースがある。しかもこれは、テストでもビルドでも検出できません。 過去に決めた方針を参照して、初めて「その手は使えない」と分かる種類の判断です。
ついでにもう1つ。検索エンジンにサイトの所有者だと証明する作業で、 最初に選んだ方法は失敗しました。 アクセス解析のタグを使う方式だったのですが、この方式はタグがページの <head> という特定の場所にある必要があり、今回の作り方ではそこに入らなかったためです。 確認用のファイルを直接置く方式に切り替えて解決しました。
こちらも「導入した」と「要件を満たしている」が別だった例です。
いまの正直な現在地
基準日: 2026年8月17日(公開2日目)
| 項目 | 状態 |
|---|---|
| 公開状態 | 🟢 一般公開中(https://typing.sakaki-lifejourney.com) |
| 独自ドメイン | 🟢 接続済み |
| アクセス解析 | 🟢 GA4・Search Console とも稼働中 |
| 広告(AdSense) | 未導入(人が来ていない段階で入れても判断材料にならないため) |
| 実ユーザー | 未計測(公開2日目。有効な数字が読めるのは1週間後から) |
| 収益 | ゼロ・未検証 |
| 発音の音声 | 🟢 本生成済み。ただし人の耳での品質チェックは未実施 |
| 実機のスマホ | 🔴 未検証(テストはエミュレーションのみ) |
| サービス名の商標 | 🔴 未調査 |
「3日でWebアプリを作って公開できた」は事実です。でもそれは動くものが世に出たという意味でしかありません。 使われるかどうかも、1円でも生むかどうかも、まだ何も分かっていません。
そして最後の2行は、この記事の主題そのものです。 「エミュレーションで検証した」は「実機で動く」を保証していないし、 「名前を決めた」は「その名前を使ってよい」を保証していません。 どちらもまだ確かめていないので、確かめていないと書いています。
次に検証すること
- 実機のスマホで成立するか — テストはエミュレーションのみ。ここは自分で触るしかない
- 公開1週間(8/22)で、そもそも人が来て、ゲームを開始して、最後まで終えるか
- 検索需要を実際に拾えるか(Search Console の実測。サイトマップは送信済み)
- 公開1か月(9/14)で再訪が生まれるか(Daily・Reviewの設計が効くか)
- 広告収益が1人運営で成立する水準か
そのうえで、続ける / やめる / 広げるを判断します。
この続きは、1週間後と1か月後に数字を持って書きます。 人が来なかったなら、来なかったと書きます。やめると決めたなら、やめたと書きます。 今回のように「まだ分からない」で終わらせずに済むのは、そこからです。
実際に触ってみたい方へ
この記事で書いたアプリは、登録不要・完全無料で今すぐ使えます。
👉 https://typing.sakaki-lifejourney.com
an apple を打つ感覚だけでも試してもらえると、この記事で書いた 「読むと目が滑るが、打つと必ず通る」の意味が1分で分かると思います。 アプリの詳しい紹介は /typein/ にあります。
⚠️ スマートフォンの実機ではまだ検証できていません。 うまく打てなかった場合は、その端末名とブラウザ名を教えてもらえると本当に助かります。 直したうえで、続報に「実機で何が起きたか」として書きます。 報告先: X(旧Twitter)@st0ck_trade8282 へのリプライ または本サイトのお問い合わせから。ひと言で構いません。
まとめ:サインを読むのではなく、何を保証しているかを読む
3日間で遭遇した「サインと保証のズレ」を、全部並べるとこうなります。
| # | 出ていたサイン | 実際に保証されていたこと |
|---|---|---|
| 1 | 型チェックとテストが全部通った | 通した検証の種類の分だけ。本番ビルドは落ちていた |
| 2 | AIの採点が4.0/5.0・重大不具合ゼロ | バグがないこと。方針が合っているかは別 |
| 3 | --target=preview と明示した | 何も。Production扱いになっていた |
| 4 | ドメインが名前解決した | 何も。wildcardが全部拾っていただけ |
| 5 | 管理画面が「保存しました」と出した | その画面に保存されたこと。効いているとは限らない |
| 6 | canonicalタグを出力していた | タグがあること。宣言先が正しいかは別 |
| 7 | 最速の手段が使える状態にあった | 速さだけ。別サイトの計測データが壊れるところだった |
| 8 | 所有権確認の方式を選んで導入した | 導入したこと。要件を満たしているかは別 |
| 9 | 「3日で公開できた」という数字 | 経過日数だけ。指示書を書いた時間は測っていない |
最後の1行は、この記事そのものへの自己適用です。 私が冒頭で出した「3日」という数字も、何を含んでいるかを言わなければ、 上の8件と同じ種類のサインでしかありません。
そのうえで、今回の結論です。
- AIに指示書を渡したら、設計から公開Previewまで1日、本番公開まで3日で到達した
(4,072行・42ページ・70語・5モード)
- AIによる第三者テストは有効だった。自分では見つけられない期待とのズレを3件出してきた
- AIはUIの問題も指摘していた(5点中3点)。それでも直らなかったのは、それが方針の問題だったから。
→ AIに渡せないのは能力ではなく優先順位
- 失敗は「AIの賢さ」ではなく「実行環境の状態」から起きた。だから設定で構造的に潰した
- 公開工程の罠は3つとも、「できているように見えるサイン」を信じたら踏んでいた。
判定を管理画面から実測へ移すだけで、全部事前に防げた
- そして今のところ、証明できたのは「作れる」と「公開できる」まで。
使われるか・稼げるかは、これから1か月かけて測る
AIに任せられる範囲は、思っていたよりずっと広がっていました。 でも「そのサインが何を保証しているか」を知っている人の席は、まだ空いていません。
同じ枠組みで実験している他の記録は Build / Experiment にまとめています。 このサイトで数字をどう扱うかは このサイトの数字と検証方針 に書いています。


コメント