何を重なりとみなすかは、施設の使われ方に合わせています。ビジターやコワーキングはフロアを共有するので互いを妨げず、会議室は時間帯が重なったときだけ、1日貸切はその日のすべての予約とぶつかります。カレンダーには空いている枠しか出しませんが、開いてから送信するまでに埋まることがあるので、サーバーは書き込む前にもう一度確かめます。ほぼ同時に届いた2件はどちらもこの確認を通ってしまうため、登録した後にその日の予約を読み直し、先に入った予約と重なっていれば自分を取り消します。「先」は作成時刻で決め、同時なら予約IDで決めるので、2件の順番の見方が食い違うことはなく、両方が取り消し合うこともありません。取り消す側は、メールを送る前に消えます。
05 — コワーキング / 予約 / 2026
WORXMT.FUJI
富士市吉原のコワーキングスペース「橘香堂(worx mt.fuji)」のサイト。施設と料金の案内に、会員登録なしで使える予約、パスワードのいらないマイページ、スタッフ用の予約管理画面を組み合わせました。
2026静岡県富士市吉原
- クライアント
- 橘香堂(近藤薬局)
- 領域
- コワーキング / 予約
- 担当
- デザイン、開発、予約システム、管理画面、SEO、運用
- 年
- 2026
01 / PROJECT
WHAT THE
PROJECT IS.
橘香堂は富士市吉原にある、着席80名・立席150名まで入るコワーキングスペースです。時間単位のビジター利用、月額の会員、会議室、住所登録のほか、イベントや1日貸切にも使われています。サイトでは空間と設備、料金、アクセス、よくある質問を、利用シーンごとのページに分けて案内しています。
予約は、利用種別、カレンダーでの日時選択、連絡先の入力、確認の4ステップで、会員登録は求めません。受付メールには予約ごとの確認リンクが付き、そこから内容の確認と、前日17時までのキャンセルができます。同じメールアドレスの予約は、メールで届くログインリンクから開くマイページにまとまります。
スタッフ側には予約管理の画面を用意しました。今日・今後7日間・確認待ちの件数から始まり、名前や電話番号での検索、確定とキャンセル、電話で受けた予約の登録、日時の変更、お客様には見えない店内メモまでを扱えます。デザインと実装から、予約の仕組み、管理画面、SEO、Cloudflareへのデプロイと運用まで一貫して担当しています。
02 / HOW IT WORKS
THE DECISIONS
UNDER IT.
実装から
スタッフが登録・変更する予約がほかと重なる場合は、止めずに警告し、承知の上で保存できるようにしています。保存した後にもサーバーで確かめ直します。確認から保存までの間に、Web予約やもう一人のスタッフが同じ枠を押さえているかもしれないためです。確定とキャンセルは、想定した状態のままの予約にだけ効くので、お客様が同じ瞬間にキャンセルした予約を確定で上書きすることはなく、スタッフには状態が変わっていると伝えます。お客様のキャンセルも同じ仕組みで、実際に行が変わったときだけメールを送るので、二重に押しても2通は届きません。キャンセル済みの予約は元に戻せません。その枠がほかの人に渡っているかもしれないため、登録し直す運用にしています。
受付メールのリンクは予約IDにHMACの署名を付けたもので、受け取った本人だけが確認とキャンセルをできます。そのためにデータベースへ何かを保存することはありません。前日17時というキャンセルの締切は、サーバーの時計がどのタイムゾーンでも日本時間で計算し、月末や年末をまたいでも正しく出ます。マイページはメールでログインします。15分有効のリンクから30日間のhttpOnly Cookieに切り替わり、2つは別の用途として署名しているので、互いの代わりには使えません。ログインの画面は、そのアドレスに予約があってもなくても同じ応答を返し、メールは応答した後に送ります。応答時間からも、予約の有無が分からないようにするためです。
管理画面はCloudflare Accessの内側にあり、許可したメールアドレスにだけワンタイムコードが届きます。アプリ側はそれを前提にせず、管理用の操作のたびにAccessが署名したトークンを自分で検証します(発行元、対象、署名方式、許可リストにあるメールアドレス)。Accessの設定が漏れていても、workers.devのアドレスに直接来たリクエストでも、予約データは返りません。設定そのものがなければ、開けずに拒否します。データベースは行レベルセキュリティを有効にしたうえでポリシーを置かず、公開用のロールには権限を与えていません。名前・メール・電話番号に触れられるのは、server-onlyを付けたモジュールでサービスキーを持つサーバーのコードだけです。
動いているのはCloudflare Workersの無料プランで、1リクエストあたりのCPU時間は10msまでです。incremental cacheが未設定だったため、ビルド時に生成したページまでリクエストのたびに描画し直し、この上限を超えてError 1102を返していました。いまは生成済みのページを静的アセットのキャッシュから、Next.jsの処理を通さずに返しています。マイページや予約の確認ページ、管理画面のように見る人によって変わる部分はブラウザ側で読み込み、データはサーバーアクション経由で取るので、ページ自体は静的なままです。
03 / DELIVERED
WHAT WAS
BUILT.
- 01
施設・空間・料金・アクセス・よくある質問のページと、利用シーン別の4つの詳細ページ
- 02
空き状況を反映したカレンダー、会議室の開始〜終了の範囲指定、1日貸切に対応した、会員登録のいらない4ステップの予約
- 03
予約ごとの署名付きリンクを載せた受付メールと、前日17時までのWebキャンセル
- 04
メールのログインリンクで開くマイページ:今後と過去の予約、キャンセル、メールアドレス・名前・電話番号を入れた状態で開く予約フォーム
- 05
予約管理画面:今日・7日間・確認待ちの件数、5つの表示切替、検索、メール通知を選べる確定とキャンセル、電話予約の登録、重なりを警告する日時変更、店内メモ
- 06
6種類の問い合わせフォームと、施設への通知・送信者への控え
- 07
設備と間取りを描いた製図風のSVGと、CSSだけで動く描き出しとループ(動きを減らす設定では静止)
- 08
公開フォームすべてのボット対策、ログインメールの送信回数制限、店舗の構造化データ、ページごとのタイトルとSNS表示、正規ドメインへのリダイレクト
04 / TECHNOLOGY
THE STACK
BEHIND IT.
- Next.js
- React
- TypeScript
- Cloudflare Workers
- Cloudflare Access
- Supabase
- Resend
- Turnstile
- Tailwind CSS
- Jest

