【IT】診察に役立つお薬記録アプリをPWAで作る:SvelteKit実装とiPhoneの壁(第1回)
はじめに
皆さま、こんにちは。
本日は、狭心症で使用するお薬の使用記録アプリについてお話しします。
発作時に服用するお薬の場合、その使用記録をつけることが多くあります。
しかし、手書きの記録だと、診察のたびに主治医から
「最近いつ使いましたか?」と聞かれても答えに詰まる——そんな経験はありませんか?
そこで私は、Webだけで完結し、CSVで医師に見せられる小さな記録アプリを個人開発しました。
本連載では SvelteKit × PWA × IndexedDB を使った開発事例を、
特に iPhoneは圏外では起動しない/一部のみキャッシュ表示の可能性 という現実的な制約も含め、
3回に分けてコンパクトに解説していきます。
狭心症・異形狭心症とは?
狭心症は、心臓を動かすための血管(冠動脈)が一時的に狭くなり、
心筋への血流が不足することで胸の痛みや圧迫感が生じる病気です。
発作は数分から数十分続き、安静や薬で治まることがありますが、
重症化すると心筋梗塞に進行する恐れがあります。
異形狭心症は、冠動脈の一部が突然けいれんのように収縮し、
血流が途絶えることで起こります。夜間や早朝、安静時に発作が出ることが多く、
痛みは強く、時に不整脈や失神を伴うこともあります。
治療と発作時対応
発作時には、ニトロスプレー(ニトログリセリン舌下スプレー) を
口の中に噴霧し、冠動脈を拡張させて血流を回復させます。
薬の効果は迅速ですが、いつ・どのくらい使用したか を正確に記録しておくことは、
診断・治療方針の見直しに非常に重要です。
なぜ記録アプリが必要か
紙のメモや記憶だけでは、発作時刻や回数の記録が漏れることがあります。
特に異形狭心症は夜間発作が多く、寝ぼけた状態で使用した記録を
翌朝に忘れてしまうケースも少なくありません。
このアプリは 「発作発生から薬の使用時刻までを簡単に残す」
ことを目的に設計され、医師にCSV形式で共有できるようになっています。
第1回:アプリ開発のきっかけと「iPhoneの壁」
―― PWAとは?Service Workerの役割と、二重登録を避ける設計
(完成版URL/使用方法/免責・提供環境の追記)
連載は全3回
第1回:背景・PWA/Service Workerの基礎・iPhoneの制約(+URL/使い方/免責/提供環境)
第2回:実装の核心(IndexedDB設計/CSV入出力/残量ロジック)
第3回:運用と見せ方(診察での提示、バックアップ、今後の改善)
✅ 限定公開URLと推奨環境
限定公開URL:https://nitro-spray-v3.pages.dev
※予告なく、公開を終了したり、クラウドホスティングサービスを変更することがございます。あらかじめご了承ください。推奨環境:
Android / PC:Chrome, Edge, Firefox, Safari(最新)
iPhone / iPad(iOS Safari):ホーム画面追加は可能。ただし 圏外では起動しません。
事前にオンラインで開いておけば、一部画面や静的資産がキャッシュで表示される場合がありますが、動作は保証できません。
🧭 使い方(かんたんガイド)
1) 初回だけやること
a. 上のURLをオンラインで開く
b. メニューから 設定をクリック
b-1. スプレーIDを設定(これは、スプレー交換毎に実施)
b-2. スプレーの使用期限を設定(これは、スプレー交換毎に実施)
b-3. 空プッシュ補正値を入力(ご自身の利用で適宜変更)
b-4. 初回使用時に空プッシュする(ご自身の利用で適宜変更)
c. PWA化(任意)
・Android/PC:アドレスバー右端の「インストール」→追加
・iPhone/iPad:Safariの共有 → ホーム画面に追加
※圏外では起動しません。
必要画面は事前にオンラインで開いてキャッシュしておくと、
後で一部が表示できる場合があります。
※スプレーを使い切ったらスプレーを交換し、スプレーIDを加算ください。
2) 日々の記録
画面の現在時刻が自動入力
必要に応じて時刻・メモを調整
登録で保存(合計使用回数/残量目安を自動表示)
3) CSVエクスポート
「CSVダウンロード」→保存。診察時の提示に使えます(プリント可/別ウィンドウ表示も可)。
4) CSVから復元(機種変更・バックアップ戻し)
「CSVから復元」を開く
保存済みCSVを選択
取り込み実行 → 記録一覧に反映
エラー時はUTF-8 / 改行などCSVの形式をご確認ください。
※アプリ画面(PCのChrome)

このアプリは何をする?
狭心症などで処方されるニトロスプレー(ニトログリセリン舌下スプレー)の使用タイミングを、スマホで素早く記録できるWebアプリ。
インストール不要(Web)/オフライン対応(Android/PC)/CSV出力・復元が特徴です。
記録:使用時刻(自動/手動)、スプレーID、症状メモ
管理:空プッシュ補正と残量目安、複数本(ID別)管理
出力:CSVダウンロード、他端末へのCSV復元
なぜ作ったか(背景)
診察で「直近どのくらい使いましたか?」に正確に答えるのが難しかったから。
手書きは書き忘れ/時刻の曖昧さ/残量管理の煩雑さ/一覧性の低さがネックでした。
Webだけで完結し、端末に依存しない方針で、SvelteKit + PWAで個人開発しました。
PWAとは?/Service Workerの役割
PWA(Progressive Web App)は、Webアプリにインストール感やオフライン動作を与える設計。
中核は Web App Manifest(アイコン/表示モード)と Service Worker(SW)(キャッシュ制御)です。
Manifest:アイコン、アプリ名、`display: 'standalone'` 等
Service Worker:ブラウザとネットの間に挟まる小さなプロキシ。
プリキャッシュ(HTML/CSS/JS/アイコンの事前保存)と更新検知で、電波がなくても開ける範囲を作ります(Android/PCで有効)。
iPhoneの壁(重要)
圏外では起動しません(初回はもちろん、ホーム追加後でも圏外での起動は不可)。
ただし、事前にオンラインで開いていた画面や静的資産は、一部がキャッシュで表示される場合があります。
`beforeinstallprompt` はiOSで発火しないため、インストール促進UIは自作が前提です。
実運用のコツ(第3回で詳述)診察前に一度オンラインで開いておく
必要画面を事前に遷移してキャッシュしておく
重要アセット(HTML/CSS/JS/アイコン)は必ずプリキャッシュに含める
二重登録はなぜ起こる?どう避ける?
自動登録(inject)と手動登録(`virtual:pwa-register`)の併用
複数ファイル(`+layout.svelte` と `+page.svelte` 等)での重複`register()`
`/sw.js` 手動登録と `virtual:pwa-register` の併用
対策:登録は“1箇所”に統一。
本アプリは `+layout.svelte` でのみ `virtual:pwa-register` を呼んでいます(ページ側では登録しない)。
技術スタック(要点)
SvelteKit v5(adapter-static + SPAフォールバック):静的配信に最適
Tailwind CSS:レスポンシブUI
IndexedDB:端末内保存(オフラインの柱)
Vite + vite-plugin-pwa:SW自動生成・プリキャッシュ・更新検知
CSV入出力:診察提示と端末移行に直結
方針は 「Webだけで完結」。サーバーDBやログインは持たず、端末内完結+CSVで“脱出可能”にしました。
トラブルシュート(よくある質問)
iPhoneでオフラインにならない/圏外で起動しない
→ 仕様です。圏外では起動しません。オンラインで一度開いてキャッシュした画面は、一部が表示できる場合があります。CSV復元でエラー
→ CSVの文字コード(UTF-8)と列構成をご確認ください。別端末のCSVでも復元可能です。インストールボタンが出ない(PC)
→ ブラウザが古い、またはPWA未対応の可能性。Chrome/Edgeの最新を推奨。
免責事項(重要)
本アプリは個人開発の無償提供です。動作保証・個別サポートは行いません。
医療判断は必ず医師の指示に従ってください。本アプリは診断・治療を代替しません。
データは端末内(IndexedDB)に保存されます。端末紛失・ブラウザ初期化等で消える可能性があります。CSVでの定期バックアップを推奨します。
本アプリの利用により生じたあらゆる損害について、開発者は一切の責任を負いません。
提供環境について(重要)
本アプリは クラウドホスティングサービスの無料プラン 上で公開しています。
このため、提供可否や公開継続は利用中サービスのポリシーやリソース状況に依存します。
無料プランの 制限変更・停止・レートリミット発生 などにより、予告なくアクセスできなくなる可能性 があります。
安定利用を最優先する場合は、CSV の定期バックアップや、必要に応じた 自前ホスティング/有料プラン の利用をご検討ください。
次回予告(第2回)
IndexedDBのスキーマと保持期間の考え方
CSV出力・CSVからの復元の実装
空プッシュ補正と残量目安の計算
Safariの `<input type="time">` 回避や、イベント構文の混在エラー対策
では、
また次回に!
