smooth-app
전 세계 식품의 성분·영양·정보를 자유롭게 협업하고 공개하는 데이터베이스
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗飲みすぎ防止・休肝日管理アプリ
+ と手動入力の本数欄で、同じ酒をまとめて記録(DBは1レコード=1杯のまま。保存時に展開する)| 層 | 技術 |
|---|---|
| Framework | Next.js 15 (App Router) |
| Language | TypeScript |
| Styling | Tailwind CSS |
| Backend/DB | Supabase |
| Hosting | Vercel |
| Unit Test | Vitest + React Testing Library |
npm install
Supabase でプロジェクトを作成し、Project URL と anon key を取得する。
# Supabase CLI のインストール(未インストールの場合)
npm install -g supabase
# DB マイグレーションを適用
npx supabase db push
プロジェクトルートに .env.local を作成して以下を記入する。
NEXT_PUBLIC_SUPABASE_URL=https://<your-project>.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=<your-anon-key>
| 変数 | 用途 | 公開範囲 |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL | Supabase プロジェクトの URL | クライアント |
NEXT_PUBLIC_SUPABASE_ANON_KEY | Supabase の anon key | クライアント |
Discord リマインドを使う場合は以下も設定する(アプリ本体の動作には不要)。
SUPABASE_SERVICE_ROLE_KEY=<your-service-role-key>
CRON_SECRET=<任意のランダム文字列>
REMINDER_USER_ID=<auth.users.id の UUID>
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...
APP_URL=https://<your-app>.vercel.app/
| 変数 | 用途 | 公開範囲 |
|---|---|---|
SUPABASE_SERVICE_ROLE_KEY | cron から DB を読む(RLS をバイパスする) | サーバー専用。絶対に NEXT_PUBLIC_ を付けない |
CRON_SECRET | cron エンドポイントの Bearer 認証。Vercel が自動で付与する | サーバー専用 |
REMINDER_USER_ID | リマインド対象の auth.users.id | サーバー専用 |
DISCORD_WEBHOOK_URL | Discord の Incoming Webhook URL | サーバー専用(漏れると誰でもチャンネルに投稿できる) |
APP_URL | 通知に載せるアプリの URL | サーバー専用 |
本番では Vercel の Settings → Environment Variables に Production スコープで登録する。
ローカル検証は .env.local(gitignore 済み)に置く。
npm run dev
npm test # ウォッチモードで実行
npm run test:run # 1回だけ実行
npm run test:coverage # カバレッジレポート付きで実行
npm run test:ui # ブラウザ UI で確認
src/
app/ # Next.js App Router ページ(calendar / stats / templates / settings / login)
api/cron/ # Vercel Cron から叩かれる Route Handler
domain/ # ビジネスロジック(純粋関数)
components/ # UI コンポーネント
actions/ # Server Actions(drink / goal / restDay / template)
repository/ # Supabase アクセス層
lib/ # 型定義・Supabase クライアント
constants/ # 定数(飲み物カテゴリ等)
supabase/
migrations/ # DB マイグレーション
docs/ # アーキテクチャ・設計ドキュメント
npx vercel --prod
未記録の日の夜21時(JST)に Discord へ通知する。vercel.json の crons で
/api/cron/reminder を叩き、その日に飲酒記録も休肝日登録も無ければ Webhook に POST する。
記録済みの日は送らない(毎晩届く通知は読み飛ばされるようになるため)。
手元での確認:
# 認証なし → 401(302 で /login に飛ぶ場合は middleware の除外が効いていない)
curl -i http://localhost:3000/api/cron/reminder
# 認証あり → 未記録なら Discord に着弾、記録済みなら {"ok":true,"skipped":true}
curl -i -H "Authorization: Bearer $CRON_SECRET" http://localhost:3000/api/cron/reminder
# Webhook 単体の疎通確認
curl -X POST -H 'Content-Type: application/json' \
-d '{"content":"テスト"}' "$DISCORD_WEBHOOK_URL"
注意点:
0 12 * * * = 21:00 JSTCRON_SECRET が未設定だと毎晩 401 になり、通知が来ないまま静かに失敗する。デプロイ後に一度手動で叩いて確認する純アルコール量(g) = 容量(mL) × (度数 / 100) × 0.8
例:ビール 500mL 5% → 500 × 0.05 × 0.8 = 20g