尚未检测到更新。GitHub 发布版本后会显示在这里。
Poopのゲーミフィケーション
翻译准备中
正在加载完整 README。
查看完整 README ↗AI駆動でうんこ支援開発するぞ
モバイルWebで「戦う → 排便ログを残す → 仲間になる」体験を提供するアプリ。
この説明と下の技術スタックは現行の実装(旧ループ・web版)のもの。新しい企画は docs/IDEA.md、資料の一覧は docs/README.md。現行web版の構成は docsArchive/web/architecture.md、うんちくんの見た目は docsArchive/poopm-3d.md。
| 領域 | 技術 |
|---|---|
| Webアプリ | Next.js 16 (App Router) + TypeScript |
| UI | Tailwind CSS v4 + shadcn/ui |
| アニメーション | Framer Motion |
| 一時状態 | Zustand (persist) |
| 認証・DB・画像 | Supabase (@supabase/supabase-js, @supabase/ssr) |
| デプロイ | Vercel |
apps/native は同じ Supabase を使う React Native 版。ネイティブモジュール(vision-camera / fast-tflite / expo-gl)を使うため Expo Go では動かず、dev build が必要。
cp apps/native/.env.example apps/native/.env.local # EXPO_PUBLIC_SUPABASE_URL / ANON_KEY を設定
npm run ios -w apps/native # 初回は prebuild + ビルド
npm run start -w apps/native # 2回目以降は dev client へ接続
実機・クラウドビルドは apps/native/eas.json(development / preview / production)を使う。課金は RevenueCat 経由で、EXPO_PUBLIC_REVENUECAT_APPLE_API_KEY が未設定だと購入は利用不可として扱われる(iap-gateway.ts の no-api-key)。
画面構成は docs/native/screen-sequence.md、現行実装の仕様は docsArchive/web/web-spec.md。
flake.nix で固定)direnv と Nix を使う場合は、リポジトリ直下で
direnv allow を実行すると flake.nix の開発シェル(Node.js 24)が自動で有効になる。
使わない場合は Node.js 24 を各自で用意する。
.envrcは Node.js のツールチェーンを用意するだけで、アプリの環境変数は読み込まない。 環境変数は次節の.env.localから Next.js が読み込む。
# 1. 依存関係をインストール(ロックファイルどおりに固定して導入)
npm ci
# 2. 環境変数ファイルを作成
cp apps/web/.env.local.example apps/web/.env.local
# 3. .env.local に Supabase の値を記入する
apps/web/.env.local に以下を設定する。値は Supabase Dashboard の
Project Settings > API から取得する。
| 変数名 | 内容 |
|---|---|
NEXT_PUBLIC_SUPABASE_URL | SupabaseプロジェクトのURL |
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY | 公開可能キー(Publishable key / anon key) |
読み込みの仕組み:
.env.local を自動で読み込む。dotenv 等の追加設定は不要。NEXT_PUBLIC_ を付けた変数のみがブラウザへ配信される。付けない変数はサーバー側
(Server Component / Server Action / Route Handler)からのみ参照できる。.env.local は .gitignore 済みでコミットされない。コミットするのは
apps/web/.env.local.example のみ。apps/web/.env.local.example にも置かない。NEXT_PUBLIC_ を付けない。付けるとクライアントバンドルへ埋め込まれる。./scripts/setup-vercel-env.sh production。レポート分析の課金を本番で動かすには、環境変数の設定だけでは足りない。 以下を上から順に行う。
subscriptions テーブルが無いと、デプロイ後にレポート画面が落ちる。
supabase link --project-ref <本番のproject-ref>
supabase db push
テストモードの価格IDは本番モードには存在しない。 作り直しが要る。
STRIPE_SECRET_KEY=sk_live_xxx ./scripts/create-stripe-price.sh
金額を変えるなら AMOUNT=980 のように渡す(単位は円)。
前提として、Stripe Dashboard で事業者情報の登録・審査を済ませ、本番の鍵
(sk_live_...)が発行されている必要がある。サンドボックスのままでは
charges_enabled が false で、本番の課金はできない。
ローカルは stripe listen が転送するが、本番は Dashboard での手動登録が要る。
登録して初めて whsec_... が発行される。これを忘れると
「決済は通るのに権利が付かない」状態になる。
URL: https://<本番ドメイン>/api/stripe/webhook
購読するイベント:
checkout.session.completedcheckout.session.async_payment_succeededcheckout.session.async_payment_failedcustomer.subscription.updatedcustomer.subscription.deleted遅延通知型の支払い方法(コンビニ払い等)では completed が未払いのまま先に
届き、実際の成否は async_payment_* で後から知らされる。この2つを購読しないと、
正しく支払った利用者に権利が付かない。
解約・支払い方法の変更は Stripe の Customer Portal へ委ねている。 本番モードでは既定の設定が有効になっていないため、Dashboard の Settings > Billing > Customer portal で有効化する。
これを忘れると、createBillingPortalSessionAction がセッションを作れず、
課金中の利用者が解約できない状態になる。
npx vercel login
npx vercel link
./scripts/setup-vercel-env.sh production
値はローカルの .env.local からコピーしないこと。 5変数すべて本番用の
別の値になる。
| 変数 | 本番で入れる値 |
|---|---|
STRIPE_SECRET_KEY | sk_live_...(テストの鍵は使えない) |
STRIPE_PRICE_ID | 手順2で作った price_... |
STRIPE_WEBHOOK_SECRET | 手順3で発行された whsec_... |
NEXT_PUBLIC_APP_URL | https://<本番ドメイン>(末尾スラッシュ無し) |
SUPABASE_SERVICE_ROLE_KEY | 本番Supabaseプロジェクトの Service Role キー |
Preview 環境にはテストモードの鍵(sk_test_)を入れる。本番の鍵を入れると、
PRのプレビュー環境から本物の決済ができてしまう。
npm run dev # 開発サーバー (http://localhost:3000)
npm run build # 本番ビルド
npm run start # 本番サーバー
npm run lint # ESLint
スキーマは Supabase CLI のマイグレーションで管理し、TypeScript の型は
そこから生成する。詳細な手順は supabase/README.md を参照。
flake.nix の開発シェルに含まれる)--local でローカルDBに接続するため必要)db:types は起動中のDBの現状から型を作る。マイグレーションのファイルを
読むわけではないので、次の2つを先に済ませておく必要がある。
supabase start # 未起動なら起動する
supabase db reset # migrations を適用してスキーマを最新にする
npm run db:types # packages/domain/src/types/database.types.ts を生成する
supabase start は既存のDBを立ち上げるだけで、追加したマイグレーションを
適用しない。db reset を飛ばすと、スキーマ変更が反映されていない古い型が
そのまま生成される(エラーにならないので気づきにくい)。
db reset はDBを作り直すためローカルのデータは消える。
検証だけなら事前の起動は不要。db:types:check は未起動のときに一時的にDBだけ
起動し、いずれの場合も db reset でマイグレーションを適用してから検証する。
このコマンドもローカルDBを作り直すため、データは消える。
npm run db:types:check # 生成物がマイグレーションと一致するか検証する
マイグレーションを追加・変更したら必ず上記の手順で型を生成し直し、生成された
packages/domain/src/types/database.types.ts を同じコミットに含める。 再生成漏れは pre-commit
フック(型がステージされていなければ落ちる)と CI(実際に生成し直して差分を検証)
の2段階で検出する。
生成された型は apps/web/src/lib/supabase/ の各クライアントに型引数として渡してあるため、
テーブル名・カラム名・列挙値の補完と検査がそのまま効く。
Supabase クライアントを生成してよいのは features/<機能名>/actions.ts、
lib/supabase/、apps/web/src/proxy.ts の3か所だけ。ESLint は apps/web/src/ 全体を既定で
禁止し、この3か所だけを解除する許可リスト方式で構成してある。新しく
ディレクトリが増えても自動的に禁止側に入るため、黙って穴が空かない。
塞いでいる経路は次のとおり。
以上为 README 的开头部分。其余内容请阅读原文。 查看完整 README ↗