はじめに
認証付きWebアプリを個人開発するとき、毎回悩みやすいのが技術構成です。
フロントはReactで素直に作りたい。デプロイは軽くしたい。
ただし、認証・管理画面・公開ページ・料金プラン・PWA対応まで伸ばしても破綻しない構成にしたい。
そう考えたときにかなり扱いやすかったのが、次の組み合わせです。
- React + Vite + TypeScript
- Cloudflare Pages + Pages Functions
- Turso + Drizzle ORM
- Better Auth
この記事ではこの構成で認証付きアプリを組むときの設計の考え方と実装して分かった改善ポイントをまとめます。
なぜこの構成を選んだのか
この構成の狙いは、開発速度と運用の軽さを両立することです。
React + Viteならフロントの開発速度が高く、UIの試行錯誤もしやすいです。
Cloudflare Pagesを使えば、静的配信とPages FunctionsによるAPIを同じプロジェクトで扱えます。TursoはSQLite系の軽さを維持しながらリモートDBとして扱いやすく、Drizzle ORMを組み合わせるとschemaとmigrationをコード管理できます。
Better Authは、認証の土台を重くしすぎずに導入できるのがよかったです。
特に相性がよかったのは「フロントはReactで作りたいが、バックエンドを大きくしたくない」という条件でした。
技術スタック構成
今回の構成は次のとおりです。
レイヤー | 技術 |
|---|---|
Frontend | React + Vite + TypeScript |
Styling | Tailwind CSS |
Hosting | Cloudflare Pages |
API | Cloudflare Pages Functions |
Database | Turso |
ORM | Drizzle ORM |
Auth | Better Auth |
PWA | vite-plugin-pwa |
この構成の大きな利点は、フロントとAPIを同じリポジトリで持ちながら、無理にフルスタックフレームワークへ寄せなくてよいことです。
Cloudflare Pages Functions を API 層に使う
Cloudflare Pages Functionsは小規模な認証付きアプリのAPI層としてかなり使いやすいです。
フロントとAPIを同じリポジトリで管理でき、デプロイ導線も単純になります。
責務分離として、次のように役割を分けると整理しやすいです。
functions/
api/
items/
index.ts # GET /api/items, POST /api/items
[id].ts # GET /api/items/:id, PUT, DELETE
src/
lib/
server/ # Pages Functions から呼ぶサーバーロジック
api/ # クライアントから呼ぶ fetch ラッパー最初にルート層へすべてのロジックを書いてしまい、後でserver層への切り出しに苦労しました。Pages Functionsのファイルはルーティングの役割に絞り、実処理は src/lib/server/ へ切り出しておくのがおすすめです。
Turso + Drizzle ORM でのスキーマ管理
TursoとDrizzle ORMの組み合わせは、個人開発でかなり扱いやすいです。
schema定義とmigrationをコードとして残しやすいのが強みです。
特に、あとから次のような変更が入るときに価値を感じます。
- テーブルに列を追加する
- 認可用の属性を足す
- plan制御のような課金関連カラムを追加する
実際に role と plan カラムをMVP後に追加することになり、migrationを最初から回していたおかげでスムーズに対応できました。
逆に言うと、最初から次の2カラムだけでも持たせておくと後が楽です。
// schema.ts(抜粋)
export const users = sqliteTable('users', {
id: text('id').primaryKey(),
email: text('email').notNull().unique(),
role: text('role').notNull().default('user'), // 認可用
plan: text('plan').notNull().default('free'), // 利用制限用
});小規模アプリでもmigrationを最初から回しておくと、後で破綻しにくくなります。
Better Auth で認証と認可を整理する
認証付きアプリではログイン機能より認可設計の方が先に重要になることがあります。
Better Authを入れた直後は「ログインできた」で満足しがちですが、実際に必要になるのは次の制御です。
- 誰が管理画面に入れるか
- 誰が更新系APIを叩けるか
- 未ログイン時にどこへ戻すか
- ロール変更をどう扱うか
UIで隠すだけでは防げないので、Pages Functions側で必ず認可を入れる必要があります。
早めに固めておくべきポイントは次のとおりです。
- DBに
roleを持たせる - 管理ルートをloaderやguardで保護する
- 更新系APIはserver側でも認可する
- 初回admin作成のbootstrap手順を決める
特に「初回admin作成をどうするか」は後回しにしがちで、本番投入直前に慌てるポイントです。
開発初期に手順を決めておくことをおすすめします。
MVPから改善しやすいデータモデルの作り方
MVPでは要件を絞ることが大事ですが、データモデルだけは少し先を見ておく方が楽です。
最初は単一の対象を扱うだけでも、後から次のような改善が入りやすいです。
- 種別を追加したくなる
- 単位となる親モデルを入れたくなる
- planや利用制限を持たせたくなる
- 公開ページと管理画面で違う見せ方をしたくなる
そのため、次の考え方を早めに入れておくと後が楽になります。
- ルートになる単位を決める
- 主要テーブルはその単位にぶら下げる
- 種別カラムを追加しやすくしておく
- migration前提で変更する
これはReactやCloudflare Pagesの話というより、認証付きアプリ全体の設計で効いてきます。
pricing ページと利用制限を後から足すときのポイント
MVPのあとで入りやすい改善のひとつが、pricingページや利用制限です。
ただし、UIだけでは成立しません。
次をセットで実装することが重要です。
- pricingページで差分を説明する
- 現在のplanと使用状況をUIに出す
- 保存前に制限到達を案内する
- 最後はserver側で強制する
Freeプランの上限のような制御は、API側で止めないと回避されます。
Reactの画面に注意文を出すだけでは不十分で、Pages Functions側でも必ずチェックが必要です。
PWA 対応を後付けしやすかった理由
この構成では、PWA対応も比較的後付けしやすかったです。
Viteを使っているので vite-plugin-pwa を追加して次を段階的に入れられます。
- manifest生成
- service worker登録
- install prompt表示
- standalone起動対応
- icon資産追加
MVPの段階では通常のWebアプリとして公開し、あとからPWA対応を積んでも大きく崩れにくい構成でした。
この構成で詰まりやすいポイント
認証確認が重複しやすい
レイアウト、route loader、各ページのfetchがそれぞれ認証確認を始めると、すぐに遷移が重くなります。
認証の責務とページデータ取得の責務は分けておいた方がよいです。
Better Auth の base URL まわり
ローカルと本番でoriginが変わるので、固定URLの扱いを雑にするとログイン導線が崩れやすいです。
実際にローカルでは動くのに本番だけリダイレクト先がおかしくなる問題が発生しました。BETTER_AUTH_URL を環境変数で管理し、Cloudflare PagesのEnvironment variablesに本番URLをセットしておくのが確実です。
本番投入準備は別で必要
コードが動くことと、本番運用できることは別です。
次を本番準備として別タスクで整理する方が安全です。
- Cloudflare Pages 本番環境変数
- Turso 本番DB
- Better Auth 本番URL
- migration 適用手順
- 初期admin作成手順
この構成が向いている人
この構成は次のようなケースに向いています。
- Reactでフロントを素直に作りたい
- 認証付きCRUDアプリを早く作りたい
- バックエンドを大きくしすぎたくない
- DBは軽く始めたいがmigrationはちゃんと持ちたい
- MVPのあとにpricing・plan制御・PWAまで伸ばしたい
逆に、最初から大規模なAPIや複雑な非同期処理、チーム開発前提の厳密な分割が必要なら、別構成の方が合う可能性もあります。
まとめ
React + Cloudflare Pages + Turso + Better Auth の組み合わせは認証付きアプリを個人開発で作るときにかなり扱いやすい構成です。
MVPのあとに認可強化・pricing追加・利用制限・PWA対応を段階的に積みやすいことも強みです。
これから同じような構成で認証付きアプリを作るなら、最初から次の3点を早めに入れることをおすすめします。
- roleベース認可(DBとAPI両方で)
- migration前提のschema管理
- UIとserverの両方で考える利用制限設計
この3つを先に押さえておくと、MVPのあとに改善を積むときかなり楽になります。