解説一覧

Pistochia

まもなく公開

ADHDの人のためのiPhoneアプリです。頭の中にあることを話すか入力すると、取りかかれるくらい小さなステップになって返ってきます。その日どれくらい元気かに合わせて並べてくれます。

担当
デザインと開発をひとりで
制作年
2026
使用技術
Expo · React Native · SQLite · Supabase Edge Functions · Claude · Whisper · RevenueCat
EXPO CLIENT: OFFLINE-FIRSTSQLITESUPABASE ANONYMOUS AUTHEDGE PROXY: OPERATIONALLOWLIST, QUOTASREVENUECAT: PAYWALLCLAUDE: TASK BREAKDOWNWHISPER: VOICE INTAKEFIRST OPENOPERATION IDWORKS IN AIRPLANE MODEFAIL-CLOSED LIMITS, AI_PAUSED KILL SWITCHPROMPTS LIVE SERVER-SIDE (ops.ts)

横にスクロールすると、図の全体を見られます。

アーキテクチャOFFLINE-FIRST CLIENT → OPERATION ALLOWLIST PROXY → CLAUDE / WHISPER

課題

ADHDの人にとっては、覚えておくことより、取りかかることの方が難しい場合が多いです。やることの山をまるごと溜め込むToDoアプリは、罪悪感を覚えるもののリストになってしまいます。作業の単位は、取りかかるのが楽に感じられるまで小さくしなければなりません。そしてアプリは、開いた瞬間から使えなければなりません。

どう作られているか

ローカルのSQLiteを使うオフラインファーストのExpoアプリで、マイグレーションはバージョン管理しています。ユーザーの識別にはSupabaseの匿名認証を使うので、最初のブレインダンプは、どの登録画面よりも先にできます。AIの呼び出しはすべて、操作単位で動くエッジ関数を通ります。アプリが送るのは操作名とそのパラメーターだけで、プロンプトやキーは決して送りません。エッジ関数は操作を許可リストと照合し、IPごとのレート制限、インストールごとの1日のクォータ、キルスイッチを適用します。タスクの分解はClaudeが担当し、音声は同じプロキシの裏にいるWhisperが処理します。ペイウォールはRevenueCatで、アナリティクスはユーザーが同意するまでオフのままです。

重要だった判断

  • アプリはAPIキーを持たない

    入るのは操作名で、出てくるのは構造化された結果です。APIキーはエッジ関数の中にあり、キルスイッチと、フェイルクローズするクォータと制限の後ろに置かれています。

  • オフラインファーストで動く

    タスクはスマホのSQLiteに保存し、ちゃんとしたマイグレーションもあります。次の一歩を表示するのにネットワークが必要なADHD向けツールでは、本来の対象である人たちの役に立てません。

  • 最初に使う前に登録させない

    匿名認証が、裏で識別情報を作ります。アカウント画面が出てくるのは、アプリが役に立ったあとです。

リポジトリのコード

functions/anthropic-proxy/index.tsエッジプロキシ:操作の許可リストとキルスイッチ
// The legacy free-relay surface: any request still carrying these is either
// an outdated client or an abuse probe — reject outright.
const FORBIDDEN_KEYS = ['system', 'model', 'messages', 'maxTokens'] as const;1
 
// …
const paused = Deno.env.get('AI_PAUSED');2
if (paused === 'true' || paused === '1') {
  return jsonResponse({ error: 'ai_paused' }, 503);
}
 
// …
for (const key of FORBIDDEN_KEYS) {
  if (key in body) {
    return jsonResponse({ error: 'invalid_request' }, 400);
  }
}
 
const op = body.op;
if (typeof op !== 'string' || !(op in OPS)) {3
  return jsonResponse({ error: 'invalid_op' }, 400);
}
const config = OPS[op]!;
  1. 3行目. アプリはプロンプトもモデルもトークン上限も送れません。それらはサーバー側にあり、アプリにできるのは許可リストにある操作を名前で指定することだけです。

  2. 6行目. AI_PAUSEDはキルスイッチです。環境変数1つで、再デプロイなしにAIへの支出をすべて止められます。

  3. 19行目. 未知の操作は拒否されます。APIキーは、アプリのバンドルのどこにも存在しません。

今の状況

App Store用の素材、リリースのチェックリスト、EASビルド、プロモーション動画、ウェイトリスト付きのpistochia.comの準備ができています。まずはiPhoneからで、次はApp Storeでの公開です。

次の解説修士論文:AIが書いたフィッシングメールの説明可能な検出