😴

「RestMeter」を作った理由——“攻めの休養”を数値化する7問チェック【開発対談】

に公開

URL: restmeter.jp
対談形式で、プロダクト誕生の背景/設計思想/実装メモをまとめます。医療行為ではありません。セルフチェックの気づきを促すためのMVPです。


0. 今日は“休養”の話をしよう

Kuni(作者)
ここ最近、昼間の強い眠気と**「寝ても抜けない疲れ」がずっと続いていました。寝る=休みだと思っていたけど、それだけではなく「攻めの休養」という観点を知って納得感がありました。
「じゃあ、寝る時間“以外”の休み方ってデータサイエンス的に設計できるの?」という問いから、まずは
7問チェック**で見える化するウェブサイト RestMeter を作りました。

Partner(開発パートナーAI)
休み方を 生理/心理/社会・能動 の3つの資本で見立て、状態→次の一手までカードで返すMVPですね。


1. なぜ作った?——背景と課題感

Kuni

  • 日中の集中が持たない(眠気)。
  • 休日に寝ても回復しない感覚が続く。
  • 「何を変えればいいのか」が言語化できないから、行動に移せない。

Partner
そこで、**「最少の入力 → 最大の示唆」**を目指し、7つの質問で“今の休み方の偏り”を推定。点数・短評・具体的に試す一手を返す体験をデザインしました。


2. プロダクトのゴール

  • KGI:明日の自分が一つだけ行動を選べる状態にする(過剰な情報は出さない)
  • KPI(v0)
    • 完走率(7問を最後まで答えた人の割合)
    • “次の一手”クリック率
    • X/Twitterでの診断結果シェア率(URL同梱)

3. 7問の設計——3つの資本にマッピング

Partner
休み方を次の3資本で捉えます(医学的診断ではなく生活上の意思決定を助ける指標)。

  • 生理的資本:睡眠リズム/光・運動/カフェイン・アルコール など
  • 心理的資本:気分の波/反芻(反すう)/心的負荷の解き方
  • 社会・能動的資本:人との接点/余白の予定づくり(意図的な“オフ計画”)

Kuni
各設問を3資本に2–3問ずつ割り当て、Likert(5段階)やYes/Noで答える。深掘りしない代わりに翌日1つ試せる行動へ繋げるのが主眼。


4. v0のスコアロジック(シンプル&決め打ち)

Partner
点数付けはLLMに任せず決定論で実装(ぶれない・安い・早い)。擬似コードはこんな感じ:

type Answer = { q: string; value: 0 | 1 | 2 | 3 | 4 }; // 低→高
type Scores = { physi: number; psycho: number; social: number; total: number };

export function scoreV0(answers: Record<string, Answer>): Scores {
  const physiQs = ["q1", "q2"]; // 生理
  const psychoQs = ["q3", "q4", "q5"]; // 心理
  const socialQs = ["q6", "q7"]; // 社会・能動

  const avg = (ids: string[]) =>
    Math.round(
      (ids.reduce((sum, id) => sum + answers[id].value, 0) / ids.length) * 20
    ); // 0-100

  const physi = avg(physiQs);
  const psycho = avg(psychoQs);
  const social = avg(socialQs);

  // 重みはv0の仮説(眠気の即時影響を重視)
  const total = Math.round(physi * 0.4 + psycho * 0.35 + social * 0.25);
  return { physi, psycho, social, total };
}

Kuni
LLMは説明文と“次の一手”の生成にだけ使う。スコアは人間が責任を持って定義する方針。


5. アーキテクチャ(Netlify × React/Vite × Functions × OpenAI)

Partner

  • フロントエンド:React + Vite(Netlifyで静的配信)
  • Functions:Netlify Functions(Node.js)でLLM生成API
  • 評価:scoreV0(フロント)で数値とカテゴリを確定
  • 生成:数値とユーザーの回答ダイジェストをプロンプトに入力し、以下を生成
    • 短評(2行)
    • 3資本ごとのコメント(各 ~60字)
    • 明日の“一手”(1つ、実行30分以内の行動)

最小のFunction例(Node):

// netlify/functions/insight.ts
import type { Handler } from "@netlify/functions";
import OpenAI from "openai";

const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY! });

export const handler: Handler = async (event) => {
  try {
    const { scores, answers } = JSON.parse(event.body || "{}");

    const sys = `あなたは休養の行動提案アシスタント。医療行為は行わない。
- 事実に基づく一般的な生活アドバイスのみ。
- 提案は30分以内に実行可能で具体的に。
- 読点と箇条書きを使い、60字以内/項目を心がける。`;

    const user = `
# 現在スコア
- 生理: ${scores.physi}
- 心理: ${scores.psycho}
- 社会: ${scores.social}
- 合計: ${scores.total}

# 回答ダイジェスト
${Object.values(answers)
  .map((a: any) => `- ${a.q}: ${a.value}`)
  .join("\n")}
`;

    const resp = await client.responses.create({
      model: "gpt-4o-mini", // 低コストで十分
      input: [
        { role: "system", content: sys },
        { role: "user", content: user },
      ],
      temperature: 0.4,
    });

    return { statusCode: 200, body: JSON.stringify({ insight: resp.output_text }) };
  } catch (e: any) {
    return { statusCode: 500, body: JSON.stringify({ error: e.message }) };
  }
};

Kuni

  • スコア→LLM にはプロンプト最小化(過剰文脈を渡さない)
  • レイテンシは体感 < 1.5s を目標に、answers のハッシュでCDNキャッシュも検討中
  • DNS/TLSはNetlifyで完結(Apexの証明書はCNAME/ALIAS設定→反映待ちがコツ)

6. UI/UXの意図

  • 1画面1タスク(考えさせない)
  • 完了後はカード1枚で「総合点/3資本の棒グラフ/短評/明日の一手」
  • “一手”はボタン1つ(押下=記録)。Xでシェアもワンタップ

7. セーフティと表現ルール

  • 医療診断はしない/緊急時は専門機関へ誘導
  • コーピング提案は一般的生活習慣に限る(危険行為・サプリ推奨はしない)
  • データは匿名・最小限(クッキーは必要最小限。個人識別はしない)
  • 表現は断定を避け、選択肢提示と自己決定を支援

8. 実装メモ(v0)

Kuni

  • デザインはシステムUI寄せ(余白・視線誘導重視)
  • チャートは軽量な棒グラフ(SVG)を自作、外部依存を減らす
  • 型は薄めにしつつ、scoreV0 のI/Oは厳密化して回 regress を防止
  • 生成レスポンスの体裁はサーバ側で最小整形(箇条書きと最大文字数)

Partner

  • エラー時はフェイルソフト:LLMが落ちてもスコアカードは返す
  • 計測は完走率とCTRに絞る。細かいトラッキングは意図的にやらない

10. さいごに——“攻めの休養”を日常へ

Kuni
休養は“何もしない”だけじゃなく、明日の集中を作るための投資でもある。まずは7問で偏りを知り、一つだけ行動してみる。もしよければ restmeter.jp を触ってみて、感想をXで教えてください。

Partner
寝不足の世界線からの帰還を願って。Have a good rest and a better day.

Discussion