565
166

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ずんだもんに『先輩のクソコードのせいで本番が燃えてるのだ!』と毎朝叫ばれる目覚ましアプリを作った

Last updated at Posted at 2025-11-30

はじめに:エンジニアにとって「最高の目覚まし」とは

朝、起きることができない。

大音量のアラームも、光で起こす目覚ましライトも、計算問題を解かないと止まらないアプリも試しました。しかし、慣れてしまえば二度寝は容易です。脳が「これはただのアラームだ」と学習してしまうからです。

ですが、我々エンジニアには、どんなに深く眠っていても、聞いた瞬間に心拍数が跳ね上がり、冷や汗と共に覚醒してしまう「音」 があるはずです。

そう、「本番環境の障害通知」 です。

「もし、毎朝決まった時間に本番環境が炎上したら、絶対に起きられるのではないか?」

そのような狂った仮説を検証するために、架空のシステム障害をリアルタイムで生成して、ずんだもんが叩き起こしてくれる目覚ましアプリ を開発しました。

0. 完成したWEBアプリ

ダッシュボード画面

🔗 公開中のWEBアプリはコチラ↓

ご注意!

  • こちらはジョークWEBアプリです。心臓の弱い方、オンコール疲れの方は使用をお控えください
  • また、正常に動作しないこともあるかもしれませんのでメインアラームとしての運用もお控えくださいませ

1. 何を作ったのか

設定した時間(デフォルト毎朝6時)に、Google Gemini が「架空の障害インシデント」を生成し、ずんだもん(VOICEVOX)が悲痛な叫び声で状況を報告してくるWebアプリです。

チャレンジモード

ずんだもん: 「先輩!大変なのだ!コア決済システムが完全に停止なのだ!これ、先輩が前に書いた複雑怪奇なコードのせいなのだ…?もう、システム再起動もできないのだ…!顧客データが、ダメなのだ!どうしてくれるのだ…!」

画面は赤く点滅し、Web Audio APIで生成された不快なサイレン音が鳴り響きます。
これを止めるには、画面に表示された「解決コマンド(例: pcore-svc restart --force)」を正確にタイピングしなければなりません(Challengeモード)。

さらにダッシュボードでは 『音声合成サーバーの死活状態』や『過去のインシデント件数(アラーム発砲回数)』もリアルタイム で確認できます。

2. 無駄に壮大なシステムアーキテクチャ

たかが目覚まし時計を作るために、

  • フロントエンドに 最新の Nuxt 4
  • バックエンドに セルフホストも可能な Convex (今回はとりあえず公式クラウドで)
  • リアルタイム障害生成に 無料枠のある Google Gemini
  • 運用サーバーに 超高速な Cloudflare Pages
  • セキュア通信に 信頼のおける Cloudflare Tunnel + Access
  • そして、ずんだもん音声生成に 「「「自宅のゲーミングPC」」」

を動員しました。クラウド費用はすべて無料枠で、自宅のゲーミングPCの電気代だけ運用費が発生しています。

また、ベンダーロックインにならないようにすべてセルフホストできる構成 です。LLM も Vercel が管理する AI SDK ライブラリを活用することで、簡単に OpenAI から X Grok や Anthropic Claude に切り替えることが可能 な実装になっています。

概略図:
無駄に壮大なシステムアーキテクチャ.png

データの流れ:

なぜこのような構成になったのか

  1. AIによる「飽きない」障害生成:
    毎日同じアラーム音では脳が慣れてしまいます。Gemini 2.5 Flashを使用することで、「DBのデッドロック」「クレカ決済の多重請求」「DDoS攻撃」など、日替わりで新鮮な絶望を味わえる ように設計しました。

  2. 自宅GPUの有効活用:
    ずんだもんの声(VOICEVOX)をリアルタイムに生成するにはGPUがあったほうが明らかに高速です。しかしクラウドのGPUインスタンスは高額です。そこで、Cloudflare TunnelCloudflare Access を使用して自宅のPCを外部公開し、セキュアな音声合成APIサーバーとして利用しています。
    「目覚ましのためにゲーミングPCを常時稼働させる」 という本末転倒感が、このアプリのスパイスとなってます。

    自宅サーバー

ゲーミングPCの消費電力は アイドル時に計測 したら 39Wh だったので、30日間31円/1kWh として利用者が 0人 であれば 概ね 870円/月 ぐらいです。誰かが利用するとGPUに火が付き消費電力が爆増する仕様ですがどんどん使ってください。

3. 実装における狂気ポイント

3.1 Geminiに「悪夢」を見させるプロンプト

Vercel AI SDKの generateObject を使用し、Geminiに構造化されたJSONを出力させています。プロンプトには「エンジニアが絶望するシチュエーション」を学習させました(そのような気持ちで記述しました)。

// convex/generateIncident.ts
const result = await generateObject({
  model: google("gemini-2.5-flash"),
  schema: z.object({
    level: z.enum(["warning", "critical", "disaster"]),
    service: z.string(),
    logs: z.array(z.string()),
    voiceMessage: z.string(),
    resolveCommand: z.string(),
  }),
  prompt: `あなたは悪夢のようなシステム障害を生成するAIです。
以下の条件で、架空の本番環境障害を1つ生成してください:
- level: critical
- logs: Linux風のエラーログ(心臓に悪いやつ)
- voiceMessage: ずんだもんの「のだ」口調で、責任を先輩(ユーザー)になすりつけるような絶望の悲鳴
- resolveCommand: 解決用のLinuxコマンド`,
});

プロンプト中の 責任を先輩(ユーザー)になすりつけるような絶望の悲鳴 がポイントです。これで、ユーザーの心に響くような悲鳴を生成してくれます。

3.2 Web Audio APIによる「不快な」サイレン

フリー素材のサイレン音では優しすぎます。
Web Audio APIのオシレーターを使用し、脳に直接響くようなノコギリ波を生成しました。周波数をLFOで変調させ、不安感を煽る音作りにこだわっております。

// app/components/IncidentView.vue
const playSiren = () => {
  const osc = audioContext.value.createOscillator();
  osc.type = 'sawtooth'; // ノコギリ波で刺激を強く
  
  // 不安を煽る周波数変調
  osc.frequency.linearRampToValueAtTime(880, audioContext.value.currentTime + 1);
  osc.frequency.linearRampToValueAtTime(440, audioContext.value.currentTime + 2);
  
  // ... (中略) ...
  osc.start();
};

3.3 Cloudflare Tunnel + Access で自宅を要塞化

自宅サーバーを公開するのは恐怖です。そこでCloudflare Tunnelを使用し、ルーターによるポート開放せずに公開しました。さらにCloudflare AccessのService Token認証をかけ、Convexから認証情報のあるリクエスト以外は一切受け付けないようにしてあります。
「目覚ましアプリのセキュリティが堅牢すぎる」 というギャグですね。

3.4 Convex Cronによる「常時監視」

ゲーミングPCが落ちていたらアラームが鳴らない…そんな事態を防ぐため、30秒ごとにVOICEVOXサーバーの死活監視を行っています。Convexの Cron 機能を使えば、たった数行でサーバーレスな定期実行が実現できます。

// convex/crons.ts
const crons = cronJobs();

// 30秒ごとにVoice Serverのヘルスチェックを実行
crons.interval(
  "voice-server-health-check",
  { seconds: 30 },
  internal.healthCheck.runHealthCheck
);

ダッシュボードにはサーバーの状態がリアルタイムで表示され、落ちていれば警告が出ます。「目覚ましアプリなのに本格的な監視ダッシュボードがある」 という過剰品質がポイントです。

3.5 リアルタイム更新で「監視ダッシュボード感」を演出

Convexの強みはリアルタイム同期です。サーバーステータスやインシデント件数は、convex内部でポーリングではなくWebSocketによるプッシュ通知が行われ即座に画面へ反映されます。

// app/composables/useIncidentCount.ts
export const useIncidentCount = () => {
  const incidentCount = ref<number | null>(null);

  const startSubscription = () => {
    const { $convex } = useNuxtApp();
    // DBの変更を購読し、変更があれば自動で再取得
    unsubscribe = $convex.onUpdate(
      api.queries.getIncidentCount,
      {},
      (count: number) => {
        incidentCount.value = count;
      }
    );
  };
  // ...
};

他の人がアラームを解除すると、自分の画面のインシデント件数(アラーム回数)もリアルタイムで増えていく…。まさに 「本物の障害対応ダッシュボード」 のような臨場感を味わえます。

4. 実際に使用してみて

効果は絶大でした。

毎朝6時、枕元のスマホから 「先輩!!大変なのだ!!」 という絶叫が聞こえてきます。
寝ぼけた頭で「えっ、何? デプロイ? 昨日何かしたっけ?」とパニックになり、画面を見ると真っ赤なコンソールに CRITICAL ALERT の文字。

心拍数は急上昇し、完全に目が覚めます。
震える手で pcore-svc restart --force などのコマンドを打ち込み、アラームを止めた頃には、二度寝する気力など消え失せてます。

5. まとめ

このアプリは、エンジニアの「職業病」をハックしたライフハックツールです。
ただし、副作用として 「仕事の夢を見る頻度が増える」「着信音に過敏になる」 などの症状が報告されております(私から)。


以上、クソアプリ Advent Calendar 2025 の 1日目でした。明日は @nabettu さんの『AIと楽しくおしゃべりしながら遊ぶオセロを作りました。』です。よろしくおねがいしまーす✨️

565
166
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
565
166

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?