---
title: "Next.js + Cloudflare Workersでお薬手帳アプリを開発した記録 | C#もぐもぐ"
description: "マイナポータルの薬剤情報CSVを取り込み、服薬管理・副作用記録・在庫予測などを行う個人向けお薬手帳アプリを開発した記録です。"
url: "https://blog.223n.tech/posts/238/"
---

# Next.js + Cloudflare Workersでお薬手帳アプリを開発した記録

2026年4月13日

[Cloudflare](https://blog.223n.tech/tags/Cloudflare/) [TypeScript](https://blog.223n.tech/tags/TypeScript/) [Hono](https://blog.223n.tech/tags/Hono/) [Next.js](https://blog.223n.tech/tags/Next.js/) [Program](https://blog.223n.tech/tags/Program/)

> ***注意***\
> この記事の内容は、開発途中のものです。\
> 今後、変更などを行う可能性が高いのでご注意ください。

## はじめに

病院や薬局でもらう処方情報を自分で管理したいと思い、
個人向けのお薬手帳アプリ「`my-okusuri-book`」を開発しました。

マイナポータルからダウンロードできる薬剤情報CSVを取り込み、
服薬記録、副作用メモ、残薬数の予測などを一元管理できるアプリです。

この記事では、技術スタックや主な機能、設計上の工夫について紹介します。

## 技術スタック

### バックエンド

| 項目 | 技術 |
| - | - |
| ランタイム | Cloudflare Workers |
| フレームワーク | Hono 4 |
| データベース | Cloudflare D1（SQLite） |
| ストレージ | Cloudflare R2 |
| バリデーション | Zod |
| 言語 | TypeScript 5.9 |
| 認証 | Cloudflare Access（JWT） |

### フロントエンド

| 項目 | 技術 |
| - | - |
| フレームワーク | Next.js 15（App Router） |
| UIライブラリ | React 19 |
| データ取得 | TanStack Query 5 |
| スタイル | Tailwind CSS + デジタル庁デザインシステムトークン |
| UIコンポーネント | shadcn/ui（New York）+ Radix UI |
| グラフ | Recharts |

### 共通・開発ツール

| 項目 | 技術 |
| - | - |
| モノレポ | pnpm Workspaces + Turborepo |
| テスト | Vitest + Playwright + Testing Library |
| CI/CD | GitHub Actions |
| コード品質 | ESLint + Prettier |

車両管理アプリ（vehicle-management）と同様にCloudflare Workers + D1の構成ですが、
フロントエンドはNext.js 15のApp Routerを採用しました。

UIにはshadcn/uiとデジタル庁デザインシステムのカラートークンを組み合わせています。

## プロジェクト構成

pnpm Workspaces + Turborepoによるモノレポ構成を採用しています。

```
my-okusuri-book/
├── apps/
│   ├── api/              # Hono APIバックエンド
│   │   ├── src/
│   │   │   ├── routes/       # APIエンドポイント（21ファイル）
│   │   │   ├── repositories/ # データアクセス層（25ファイル）
│   │   │   ├── services/     # ビジネスロジック
│   │   │   ├── parsers/      # CSV解析（6ファイル）
│   │   │   └── middlewares/   # 認証・エラーハンドリング
│   │   └── migrations/       # D1マイグレーション（31ファイル）
│   └── web/              # Next.jsフロントエンド
│       └── src/
│           ├── app/          # App Routerページ（25以上）
│           ├── components/   # UIコンポーネント（18フォルダ以上）
│           └── hooks/        # API連携フック（20以上）
├── packages/
│   └── shared/           # 共有スキーマ・型定義
│       └── src/
│           ├── schemas/      # Zodバリデーションスキーマ（13ファイル）
│           └── types/        # 列挙型・DB行型
├── e2e/                  # Playwrightテスト
├── docs/                 # ドキュメント（日本語）
└── sample/               # テスト用CSVデータ
```

`packages/shared`でAPIとフロントエンド間のスキーマ・型を共有しています。

Zodスキーマを共有することで、バリデーションロジックの重複を排除し、型安全性を確保しています。

## 主な機能

### CSV取り込み

マイナポータルや電子版お薬手帳からダウンロードしたCSVを取り込めます。次の3形式に対応しています。

- マイナポータル薬剤診療情報CSV
- マイナポータル調剤情報CSV
- JAHIS電子版お薬手帳CSV

CSVの形式はアップロード時に自動判定します。

取り込み時には医療機関、薬剤、処方箋のデータを一括で登録し、取り込み履歴を記録します。

誤って取り込んだ場合は、ロールバック機能で取り込み前の状態に戻せます。

### 服薬管理

処方された薬剤ごとに、服用タイミング（朝・昼・夕・就寝前・その他）と用量を設定できます。

日次の服薬記録画面では、各タイミングの服用状況を記録します。

ダッシュボードには7日分×4タイミングのカレンダー形式で服薬状況を表示し、
服用完了時にはスタンプアイコンが付きます。

### 残薬管理・在庫予測

残薬数を記録すると、服用スケジュールに基づいて在庫切れ予測日を自動計算します。

在庫が少なくなった薬剤はダッシュボードでアラート表示されるため、処方の再取得タイミングを把握できます。

### 副作用記録

薬剤ごとに副作用のメモを記録できます。

さらに、PMDA（医薬品医療機器総合機構）のJADERデータを参照して、薬剤の副作用統計情報を確認できます。

ORCA（日本医師会標準レセプトソフト）のデータベースを使った薬剤相互作用のチェック機能も実装しています。

### 薬剤情報

厚生労働省の医薬品マスターとの連携により、薬剤の詳細情報を取得できます。

RAD-AR（くすりのしおり）のデータをキャッシュして、薬の説明情報も提供しています。

### 日常記録

服薬記録のほかに、次のような日常の健康情報を記録できます。

- 食事記録（写真付き、R2ストレージ保存）
- 健康測定タスク（血糖値、血圧など）
- 通院予約の管理
- 診察メモ
- OTC医薬品（市販薬）の記録
- 患者プロフィール（アレルギー、既往歴など）

### ダッシュボード

ダッシュボードでは、次の情報を一覧表示しています。

- 当日の服薬状況（7日カレンダー）
- 在庫アラート（在庫切れ予測日付き）
- 通院予約のリマインダー
- サマリー統計

## データベース設計

D1（SQLite）に21のコアテーブルを定義しています。

マイグレーションは31ファイルで管理しています。

主要なテーブルは次のとおりです。

| テーブル | 用途 |
| - | - |
| medications | 薬剤マスター |
| prescriptions | 処方箋 |
| prescription_items | 処方明細 |
| medication_logs | 服薬記録 |
| medication_stocks | 残薬数・在庫 |
| side_effect_notes | 副作用メモ |
| medical_institutions | 医療機関 |
| daily_tasks | 日常タスク定義 |
| daily_task_logs | タスク実行記録 |
| meal_logs | 食事記録 |
| appointments | 通院予約 |
| drug_master | 医薬品マスター |
| orca_interactions | 薬剤相互作用 |
| jader_adverse_events | JADER副作用データ |
| import_logs | 取り込み履歴 |

## 認証

個人利用を前提としたアプリのため、Cloudflare AccessのJWT（RS256署名）で認証しています。

公開鍵はCloudflare Accessのエンドポイントから取得し、1時間のTTLでキャッシュしています。

開発環境では検証をスキップするフォールバックも用意しています。

## テスト

テストは3種類を実装しています。

- **ユニットテスト（Vitest）**: CSV解析、在庫計算サービス、ユーティリティ、認証ミドルウェア
- **インテグレーションテスト**: 取り込みフロー、薬剤クエリ、在庫計算の結合テスト
- **E2Eテスト（Playwright）**: ダッシュボード、ナビゲーション、フォーム操作

フロントエンドのコンポーネントテストにはTesting Libraryを使っています。

## CI/CDとデプロイ

GitHub Actionsで5つのワークフローを構成しています。

| ワークフロー | 用途 |
| - | - |
| ci.yml | PRチェック（テスト・型チェック・ビルド） |
| deploy-api.yml | APIデプロイ + D1マイグレーション |
| deploy-web.yml | フロントエンドデプロイ（Cloudflare Pages） |
| release.yml | バージョンタグ・リリースノート |
| deploy-docs.yml | TypeDocドキュメント生成 |

開発環境（developブランチ）と本番環境（masterブランチ）で自動デプロイを分けています。

## おわりに

マイナポータルの薬剤情報CSVを取り込める個人向けお薬手帳アプリを開発しました。

フロントエンドにNext.js 15 + shadcn/ui、バックエンドにCloudflare Workers + Honoという構成で、
モダンなUIと低コストなインフラを両立しています。

JADER副作用データやORCA相互作用データなど、日本の医療データベースとの連携を実装したことで、
単なる記録アプリにとどまらない安全性チェック機能を持たせることができました。

今後は、処方変更の履歴比較機能や、お薬手帳データのPDF出力など、
さらなる機能の追加を検討しています。

## 参考サイト

- [Next.js ドキュメント](https://nextjs.org/docs)
- [shadcn/ui](https://ui.shadcn.com/)
- [TanStack Query](https://tanstack.com/query)
- [Cloudflare Workers ドキュメント](https://developers.cloudflare.com/workers/)
- [Cloudflare D1 ドキュメント](https://developers.cloudflare.com/d1/)
- [Cloudflare R2 ドキュメント](https://developers.cloudflare.com/r2/)
- [Hono](https://hono.dev/)
- [Zod](https://zod.dev/)
- [マイナポータル](https://myna.go.jp/)
- [JADER（医薬品副作用データベース）](https://www.pmda.go.jp/safety/info-services/drugs/adr-info/suspected-adr/0003.html)
- [Turborepo](https://turbo.build/repo)
- [Vitest](https://vitest.dev/)
- [Playwright](https://playwright.dev/)

[記事一覧に戻る](https://blog.223n.tech/posts/)
