毎日の睡眠を24時間タイムラインで記録し、受診時の帳票としても使えるWebアプリ「sleep-diary-php」を紹介します。
睡眠に悩む方のセルフケアと、医療機関での受診補助を目的に作りました。
本番環境はhttps://sleep.223n.tech/で公開・稼働中です。
睡眠日誌とは
睡眠日誌は、就寝・起床の時刻や夜間の目覚め、日中の眠気などを日々書きとめる記録です。
不眠症や過眠症の診療では、患者さん自身がつけた睡眠日誌が診断や治療方針の重要な手がかりになります。
紙の用紙に手書きする方法が一般的ですが、次のような悩みがつきまといます。
- 用紙を持ち歩くのが手間で、記録が抜けやすい
- 何時間眠れたのか、合計や平均を毎回自分で計算する必要がある
- 数か月分をまとめて振り返りにくい
このアプリは、こうした手書きの負担を減らしつつ、医師に見せられる帳票の形を保つことを目指しています。
何ができるのか
24時間タイムラインで直感的に記録する
記録の中心は、正午から翌正午までを30分刻み48スロットで表した24時間タイムラインです。
眠っていた時間帯をタップして塗るだけで、1日の睡眠が視覚的に入力できます。
タイムラインは3列で構成します。
- 状態列は、睡眠・在床覚醒(床に着いたが眠れていない)・強い眠気を記録します
- 服薬・食事列は、睡眠薬などの服薬と食事を点で記録します
- 入浴列は、入浴した時刻を点で記録します
状態は相互排他で同じ時間帯に1つだけ、服薬と食事は同じ時間帯に両方を記録できます。
備考のほかに、服薬メモと非公開メモも持てます。
非公開メモは本人だけが見るためのもので、医師へ渡すPDFには載りません。
一覧・詳細・集計で振り返る
一覧画面では、月単位で各日の睡眠を横並びのチャートとして見渡せます。
未記録の日は空白行として表示し、タップするとその日の記録をすぐに作成できます。
詳細画面では、1日ごとに合計睡眠時間・中途覚醒回数・就寝と起床の時刻・服薬回数などの集計を表示します。
さらに推移グラフでは、睡眠時間の日次バーと7日移動平均を重ねて、傾向の変化を追えます。
受診共有サマリと印刷帳票
医療機関へ持っていくための出力も用意しています。
- 受診共有サマリは、直近4週・8週・12週を1ページにまとめた要約です
- 印刷帳票は、年月を選んで1か月分を印刷用に整えた紙の日誌形式です
印刷帳票は未記録の日も空欄で出力するため、手書き用の白紙帳票としても使えます。
これらはサーバー側でPDFを生成してダウンロードできるので、印刷機能が使いにくいiOSのホーム画面アプリでも確実に保存できます。
記録を続けるための工夫
記録は続けてこそ意味があります。
- 記録リマインダーは、前夜が未記録のときに朝・昼・夜の指定時刻へ通知します(メールとアプリ通知に対応)
- 継続支援カードは、連続記録日数や直近7日の記録日数を表示して習慣化を後押しします
- オフライン対応(PWA)により、一度開いた入力ページは電波の届かない場所でも入力でき、オンライン復帰時に自動で同期します
安心して使うためのセキュリティ
睡眠のデータは、健康に関わる繊細な個人情報です。
そのため、認証とプライバシーの保護に力を入れています。
- パスキー(WebAuthn/FIDO2)に対応し、メール入力なしの生体認証や画面ロックでログインできます
- 二要素認証(TOTP)に対応し、パスワードログイン時に認証アプリの6桁コードを追加で確認します
- ログイン中の端末を一覧・失効でき、新しい端末からのログインは本人へメールで通知します
- 自分の全データをCSVやJSONでエクスポートでき、退会すれば関連データごと完全に削除します
データはユーザーごとに厳密に分離し、他人の記録は参照も編集もできません。
新規登録は管理者が発行した招待リンク経由に限る招待制で、誰でも勝手に登録できない仕組みです。
技術的なこだわり
ここからは、開発者向けに実装のこだわりを紹介します。
技術スタック
- フレームワークはCakePHP 5系、言語はPHP 8.3、データベースはMySQL 8.0です
- フロントエンドはサーバーサイドレンダリングと手書きCSS 1枚で構成し、npmやビルドツールを使いません
- アクセシビリティはデジタル庁デザインシステム(DADS)とカラーユニバーサルデザイン(CUD)に準拠します
ビルド工程を持たないぶん構成はシンプルで、共有ホスティングでもそのまま動きます。
認証まわりの実装
- パスキーは
lbuchs/webauthnライブラリを用いて実装しています - 二要素認証(TOTP、RFC6238)は外部ライブラリに依存しない自前実装です
- ログイン失敗はメールアドレスと送信元IPの組で数え、1時間に5回で一時的に遮断します
- パスワード設定時は、HIBP Pwned Passwordsとk-anonymity方式で照合し、漏えい済みのパスワードを拒否します
日付と時刻の扱い
日付と時刻はすべて日本時間(JST)で扱い、「現在の対象日」は正午を基準に判定します。
深夜をまたぐ睡眠区間を正しく1日として扱うための設計です。
開発と本番の二層構成
開発環境はDockerとDevContainerでそろえ、本番はさくらのレンタルサーバー(スタンダード)で運用します。
本番は共有ホスティングでDockerを使えないため、git archiveとSSHを組み合わせてデプロイします。
品質を支える仕組み
- 静的解析はPHPStan(level 8)とPHP_CodeSniffer(CakePHP規約)で行います
- テストはPHPUnitで、行カバレッジ100%をCIの必須ゲートにしています
- push前のフックでlintとテストを自動実行し、失敗時はpushを中止します
これらの仕組みにより、機能追加のたびに品質を確認しながら安全に開発を進められます。
おわりに
sleep-diary-phpは、睡眠に悩む方の毎日の記録を支え、医師とのコミュニケーションを助けることを目指したアプリです。
手書きの負担を減らしながら、診療で役立つ帳票の形を保つ点にこだわりました。
興味を持たれた方は、ぜひ次のリンクをご覧ください。
- サイト:https://sleep.223n.tech/
- ソースコード:非公開
ライセンスはMIT Licenseです。