
こんにちは、キクです。
少し前までは「Codex、気にはなるけど使えていない」という状態だった筆者ですが、最近は少しずつ小慣れてきたかなという感じになってきました。
そこで、以前から「自分用のポモドーロタイマーアプリ制作」というものに興味があったので、今回はCodexを使ってバイブコーディングでアプリ制作にチャレンジしてみました!
非プログラマーなので、実際のコードに関する深追いはしない(できない)のですが、バイブコーディングや制作物であるポモドーロタイマーアプリの雰囲気なんかを共有できればなと思ってます!
それでは、よろしくお願いします。
ポモドーロタイマーアプリの紹介
今回制作したポモドーロタイマーアプリについて、簡単に紹介していこうと思います。
ユーザインターフェース

UIとしては以下のようなシンプルな構成になっています。
「プレイリストを管理」をクリックすると、以下のようなウィザードが表示されます。

YouTube側で作成したプレイリストの共有設定時に表示されるURLを入力して登録すれば、アプリ側から再生できるようになっています。
プレイリスト内の各BGMは「前へ / 次へ」ボタンや、スクロール画面から選択できるので、気分によってBGMを選択しやすい点も気に入ってます。
「新規ポモドーロセットを登録」をクリックすると、自分の好きな配分でポモドーロタイマーを作ることができるようになっています。

「ポモドーロセットを管理」をクリックすると、登録済みのポモドーロタイマー設定を編集したり、削除できるようになっています。

制作序盤はこの辺りの操作性があまり良くなかったのですが、壁打ちしていく中でCodexがいい感じに修正してくれました!
制作工程の小話
初めてのバイブコーディング
バイブコーディングでアプリ制作をするのは今回が初めてだったのですが、前回の記事でTerraform/Ansibleを使って監視用VMをセットアップした時と同様に、まずは作りたいもの(ポモドーロアプリ)の構成イメージを伝えるところから始めました。
今回はCodexの「プランモード」という機能を使って、最初の段階でCodexと会話を繰り返してプランを立ててから制作に取り掛かりました。

自分でアプリの要件を全部伝えるのはアプリ制作に慣れていない自分にとってはハードルが高く、確実に抜け漏れが発生すると思っていたので、Codexから「これはどうする?」と聞いてきてくれるプランモードは非常に助かりました。
YouTubeプレイリスト連携機能だけは実装したかった
今回制作するポモドーロタイマーには、それほど多機能を盛り込むつもりはなく「まずは最低限使えるもの」というモチベーションでスタートしました。
ただ、「これだけは実装したい!」と考えていた機能があり、それがYouTubeのプレイリストを連携させることでした。
YouTubeで「ポモドーロタイマー」なんて検索をすると、動画とタイマーが一体化したコンテンツがたくさん出てきます。
動画投稿者様が投稿してくれたコンテンツをポモドーロタイマーとして活用できるのでありがたいですね。
一方で、普段からポモドーロタイマーを愛用する中で「好きな長尺の動画をポモドーロタイマーとして使えたら嬉しいよなー」という妄想をしていました。
そこで思い付いたのが、好きな動画とタイマーが同じブラウザ画面上で表示されていれば良さそうということでした。
ただ、ポモドーロタイマーを使う場面で毎回動画を探し回るのは面倒だったので、お気に入りの動画をプレイリストに登録しておいて、そこから選べるようにすれば快適だと考えました。
その結果「YouTubeのプレイリスト連携を実装したいな」と思ったわけです。
制作する中で「あーしたい、こーしたい」の欲が広がった
今回、バイブコーディングは作業PC上で行い、アプリ自体も作業PC上で動かすことを想定していました。
実際、できあがったポモドーロタイマーアプリを作業PC上で動かすことには成功したのですが、そこでとある欲が湧いてきました。
作業PCだけでなく、スマホやタブレットからも使えた方が便利なのでは・・・ と。
詳しくは後述しますが、作業PCとは別の仮想マシン上でアプリを動かすことで、無事にこの欲は実現することができました。
複数媒体から接続できるようにしただけですが、とても使い勝手が良くなって嬉しかったですね。
また、この改善の次にぶつかった壁が「家の中からじゃないと使えない」ということでした。
この問題についても現在は解消済みですが、僕の中でも学びが多かったことや、本記事の本質とは逸れてしまうので別の記事で紹介できればと思います!
アプリの実行環境紹介

本稿では、ポモドーロアプリの実行環境について簡単に紹介していきます。
仮想マシンで動かす
前項で「アプリを複数媒体から使えるようにしたいという欲が湧いてきた」と書きましたが、それを実現するために自宅のProxmox環境上に仮想マシンを立てて、そこにDockerコンテナとしてアプリを動かすようにしました。
作業PCでアプリを動かしていると、作業PCからは使えてもスマホからは使えなかったり、使えるようにしたとしても作業PCが起動してないと使えなかったりと、制限事項が出てきてしまうなと思いました。
その点、仮想マシンとして動かしておけば、作業PCと違って常時起動させやすく、自宅Wi-Fiに繋がっている媒体であればブラウザで「http://VMのIPアドレス」にアクセスすればポモドーロタイマーアプリに繋げられるので、使い勝手が良くなりました。
YouTubeプレイリスト連携のこと
実装はCodexに任せているのですが、どうやらYouTube IFrame APIというものを使っているようです。
アプリ画面で入力したプレイリストURLからplaylist IDを取り出して、アプリがAPIを読み込むような流れになっています。
APIの公式説明を確認してみると、次のように書かれていました。
IFrame Player API を使用すると、YouTube 動画プレーヤーをウェブサイトに埋め込み、JavaScript を使用してプレーヤーを制御できます。
この API の JavaScript 関数を使うことで、再生する動画の頭出し、動画の再生 / 一時停止 / 停止、プレーヤーの音量の調節、再生中の動画に関する情報の取得といったことができます。プレーヤーの状態の変化など、特定のプレーヤー イベントに応じて実行されるイベント リスナーを追加することもできます。
製作の初期段階では、作業 ↔︎ 休憩のタイミングではBGM自体は流れ続けたまま、切り替わりを示すアラーム音が一瞬鳴るような使用だったのですが、実際に使ってみると切り替わりが分かりにくいなと感じました。
そこで、休憩に入るのタイミングでBGMは一度停止して、休憩が終了する際にBGMも再開するように修正を入れてもらいました。
先ほどの公式説明を見ると、動画の再生や停止についてもAPIから実施できることが分かるので、どうやって実装されていたのかについて僕の中でも腑に落ちました。
アプリ側で登録した情報の保存について

複数の媒体からアプリを使えるようにしたことで気になったのが、例えばスマホから登録したプレイリストやタイマー情報はどうやって保存しているのかということでした。
Codexに聞いてみたところ、ブラウザ側でも保存しているが、大元はサーバー上に保存されていることが分かりました。
実際に確認してみると、以下のような情報がJSON形式で保存されていました。
kiku@pomo-server:/opt/pomodoro-bgm$ sudo docker compose exec pomodoro-bgm cat /app/data/state.json
{
"presets": [
{
"id": "classic-25",
"name": "Classic 25/5",
"focusMinutes": 25,
"shortBreakMinutes": 5,
"longBreakMinutes": 15,
"roundsUntilLongBreak": 4
},
{
"id": "deep-50",
"name": "Deep 50/10",
"focusMinutes": 50,
"shortBreakMinutes": 10,
"longBreakMinutes": 20,
"roundsUntilLongBreak": 3
}
],
"playlists": [
{
"id": "playlist-xxx",
"name": "テスト",
"youtubeListId": "xxx"
}
],
"settings": {
"autoAdvance": true,
"selectedPresetId": "classic-25",
"selectedPlaylistId": "playlist-xxx",
"playlistVideoIndexes": {
"playlist-xxx": 0
},
"videoMetaCache": {
"xxx": {
"title": "BGMで巡る東京ディズニーシー⑥《全編4K映像》"
},
"xxx": {
"title": "BGMで巡る東京ディズニーランド&ディズニーシー (合計5本・4時間)【総集編 2 】"
},
"xxx": {
"title": "Playlist | 어디로 가는거야? 🚀📈 지구 밖 궤도에서 그루브 탐사중 😎 | GROOVE · JAZZHOP | 카페 · 집중 · 작업 · BGM · 노동요"
},
"xxx": {
"title": "New York Vibe✨ 경쾌하게 시작하는 하루🎧 뉴욕 분위기 노동요 | 하루종일 틀어놓기 좋은 노래"
},
"xxx": {
"title": "Playlist | 기분 UP 능률 UP 🙌 적당히 신나고 듣기 좋은 경쾌한 그루브 😎 | GROOVE · JAZZHOP | 매장음악 · 카페 · 집중 · 작업 · 노동요"
},
"xxx": {
"title": "Best Relaxing Starbucks Coffee Shop Playlist - Cafe Music, Jazz BGM, 2024 Starbucks Music to Study"
}
}
}
}
普段はアプリケーションを使う消費者でしかないですが、作ってみると「こうやってデータ保持してるんだなー」など学びがたくさんありますね!
Ansible / GitHubの活用
アプリの実行環境を作業PCから仮想マシンに移行したので、コードを書く環境(作業PC)とアプリを動かす環境(仮想マシン)が分離した状態になりました。
修正したコードを仮想マシンの所定の位置に毎回配置して〜という作業などが面倒だったので、Ansibleで管理できるようにしました。
また、Ansibleに関するコードを含め、アプリに関するコード群をGitHubで管理できるようにもしました。
職場でもGitHubは利用してはいるものの、そこまで頻繁に触るわけではないので「プライベートでも利用して、慣れていこう」という意味合いが強いのですが、忘れっぽい僕の場合は時間が経つと「どのフォルダに何のコードがあったっけ?」となりかねないの、いつでもどこからでも確認できるGitHubにアップしました・・・笑
Codexでガリガリコードを修正しつつ、GitHubでバージョン管理できる状態になったので、個人的には満足です。
感想
今回初めてのバイブコーディングでポモドーロタイマーアプリの制作にチャレンジしてみましたが、正直かなり感動しました。
冒頭で各コードの深追いはしないと書いたので詳細は割愛しますが、全体像としては以下のようなコード群を生成してきました。
ポモドーロアプリ制作/
├── index.html
├── package.json
├── src/
│ ├── app.js
│ └── styles.css
├── scripts/
│ ├── dev-server.mjs
│ ├── build.mjs
│ └── server.mjs
├── Dockerfile
├── docker-compose.yml
├── ansible/
│ ├── inventory.ini
│ └── playbook.yml
├── README.md
└── DEPLOY.md
index.html
- アプリ画面の骨組み
src/app.js
- ブラウザ上で動くアプリ本体
- タイマー、YouTube連携、設定保存、ボタン操作を担当
src/styles.css
- アプリの見た目
- レイアウト、色、ボタン、スマホ対応などを担当
scripts/dev-server.mjs
- 開発中に手元PCで使う簡易サーバー
scripts/build.mjs
- 本番用の
dist/を作るビルド処理 index.htmlとsrc/をコピーする
scripts/server.mjs
- 本番用のNode.jsサーバー
- Dockerコンテナ内で常時動く
- 画面ファイル配信と
/api/stateによる保存処理を担当
package.json
npm run dev、npm run build、npm startなどのコマンド定義
Dockerfile
- アプリをDockerイメージ化するための設計図
docker-compose.yml
- Dockerコンテナの起動設定
- ポート、再起動設定、保存ボリュームを定義
ansible/inventory.ini
- デプロイ先VMの情報
- IPアドレス、ユーザー名、配置先など
ansible/playbook.yml
- VMへDockerを入れて、アプリを配置・起動する自動化手順
README.md
- アプリ概要と基本的な使い方、起動方法
DEPLOY.md
- VMやCloudflare Tunnelで公開するための詳しい手順
これだけのコードを非プログラマーの自分が書こうとすれば、一体どれだけの時間が必要になってしまうのか・・・笑
それをCodexと会話を重ねていくだけで、累計数時間でアプリができてしまうのですから、すごい時代です。
今回は個人用のアプリということもあり、あまりコードの詳細までは踏み込まずに制作を進めてきましたが、仕事で使うとか、人に提供するなどの場合にはもっとセキュリティへの意識や詳細の把握が必要にはなってくるとは思います。
とはいえ、自分のイメージしているものが形になって、自分の生活を快適にしてくれるようなアプリを自分で作れるのはとても楽しいなと感じました。
それに、先ほど登場した「YouTube IFrame API」なんてものは今回のアプリ制作をするまで知りませんでしたし、AIにコード生成を丸投げと言っても少しでも深掘れば学びになることだってたくさんあると感じました。
なので、今後も作りたいものができたらAIと協力して楽しみながら制作に取り組んでみたいなと思います!
本記事を最後まで読んでいただき、ありがとうございました。
ではでは!