ともりの困りごと研究所

読みもの / 作ってみた

公共施設の予約を、作り直してみました

卓球台を使いたかった人が、登録も本人確認も済ませたのに、使えない理由を電話で聞くまで知れなかった。
その一件から、架空の町の予約システムを作りました。動くものが触れます。しくみは自由に使えます(MIT)。

ともりの困りごと研究所 / よろず町・第一号 / 2026-08-29

見本を開く(よろず町役場/施設の予約)→
ログイン不要。スマホで開いてください。触った予約も入れた呼び名も、毎晩4時に消えて元に戻ります。

1. きっかけは、一人の声でした

体育館の卓球台を使いたくて電話したら、「予約した人が優先です」と言われた。それで予約システムに登録することにした。 登録では生年月日をカレンダーで選ぶのだが、何十年も遡る形式で、まずそこで手が止まった。 それでも、マイナンバーカードで本人確認をして、口座振替の手続きまで済ませた。

——なのに、いざ予約しようとすると使えない。問い合わせて初めて「本人確認の完了まで時間がかかります」と知らされた。
ある市が公開している「市民の声」から。原文は引用せず、状況だけを一般化しています。

この声が名指ししている困りごとは、二つあります。

二つ目のほうが重い、と考えました。説明が足りないのではなく、 いま自分がどの状態にいるかを、画面が言っていない。ここが根です。

2. 既存の予約システムを、3つの自治体で触ってみました

作る前に、規模もパッケージも違う3つの自治体(政令市・中核市・人口数万の町)の予約システムを、 実際に開いて触りました。予約は1件も入れていません。ログインもしていません。 別々のパッケージで同じことが起きて初めて「型」と呼べる、と考えたからです。

結論はひとつでした。

3つとも、「施設の台帳」を画面にしていて、「借りたい人の用事」を画面にしていない。

だから利用者は、自分がいまどの状態にいて次に何をすればいいかを、画面からではなく 別の文書——凡例・PDF・お知らせ——から読まされます。それを支える型が5つありました。

既存で起きていたこと
よろず町でどうしたか
1
入口が「探し方を選べ」から始まる。ある市は検索方法が6つ(施設種類/室場種類/利用目的/利用者区分/施設名/お気に入り)。 ある町は施設が全部で9つしかないのに、空き表の前に「どう探すか」の画面が1枚入る。 体育館1館が「全面/1/2面/1/4面/1/8面」で15行に分かれ、バドミントンをしたい人が何面ぶんを押さえればいいかは、行の名前からは決められない。
入口は空き表そのもの。「どう探すか」を聞かない。施設は5つで、5つ全部が最初の画面に出ている。 絞りたい人のために用事のボタン(卓球・会議・野球・お祭り・読書会)を置いたが、これは門ではなく絞り込み。 1施設1行で、台帳の分類名は使わない。
2
状態が、記号と凡例に追い出されている。ある市の凡例は8種類で、●と〇の違いは塗りだけ、意味は「ネットで取れるかどうか」という決定的な差。 ある町では警告の三角が「一部空き」——いちばん普通で、いちばん良い状態に、警告の記号が当ててある。 いちばん効くのは白いマスで、「情報が無い」「予約できない」「隣の続き」が同じ見た目になる。
凡例を置かない。マスに言葉を書く。マスの言葉は「空いてる」「ほかの人が使います」「◯曜日は休みです」など、 読めばそのまま分かるものだけ。白いマスを作らない。 ネット予約できない施設は表に混ぜず、電話番号を書いた行にする。
3
仮押さえ・確定の段と、取消の期限が、PDFの中にある。 ある市の60ページのガイドブックには「◯まで取り消し可能」というブロックが19個。締切の種類だけで8通り、無料で取り消せる線は6通り。 ある市では「仮押さえ/仮予約/本予約」という3つの状態の定義が、約12MBのPDFの用語集にしか書かれていない(画面に出る言葉は「申込トレイに入れる」だけ)。
取消の期限は、その予約が自分で言う。 「9月6日(日)まで無料で取り消せます。9月7日(月)からは半額、9月10日(木)からは全額かかります」—— 施設と利用日が決まれば計算できることを、利用者に60ページから探させない。 段は隠さず残す。ただし、要らない段は最初から作らない(無料・確認不要の施設は、押さえたらそのまま確定)。
4
説明が、要らないところにだけある。 トップページの最初の本文が「買い物カゴの仕組みを使っています」という比喩の解説だったり、 「ブラウザの戻るを使わないでください」という操作の段落だったり。 その一方で、何も選ばずにボタンを押すといきなりログイン画面に飛び、赤字で「IDとパスワードを入力してください」だけが出る。 予約には利用者登録が要ることも、登録に何が必要かも、その場には出てこない。
操作の説明を書かない。書きたくなったら、そこは画面が間違っている。 押さえられないマスは、その場に理由を出す——「役場の確認に3日かかります。9月1日(火)から押さえられます」。 そして告げるだけで終わらせず、押すとその日へ連れて行く。
5
スマホでは、そもそも空き表が見えない。 1020px固定の画面がそのまま390pxに縮んで本文が数ピクセルになる町。 スマホ用レイアウトはあるが、空き表の初期表示が8時〜12時の5列だけで、実際に空いている14時と20時は横スクロールの外、という市。 いちばんよく作られていた市でも、最初の1画面はお知らせ10件(うち3件は数年前のもの)で占められていた。
スマホを先に描いた。横に長い表をやめ、1日ぶんを縦に積む。 「土曜の午後空いてるかな」を調べる場所はまずスマホで、ここが見えないことは他の4つより先に効く。 横に長い表は、CSSでは直りません。型を変えないと直らない。

3. こう直しました

最初の画面 — 空き表がそのまま入口

よろず町役場/施設の予約
中央公民館の会議室
20人まで・1こま600円
午前 9:00–12:00ほかの人が使います
午後 13:00–16:00空いてる
夕方 16:30–19:00ほかの人が使います
町体育館
100人まで・1こま1,200円 ・役場の確認あり
役場の確認に3日かかります。9月1日(火)から押さえられます →

凡例はありません。押せるマスは「空いてる」と書いてあって押せる。押せないマスは、押せない理由がそこに書いてある。

押さえたあと — 予約1件が、自分の状態と期限を言う

あなたの予約
役場の確認まち
町体育館
9月12日(土) 午前 9:00–12:00 / 1,200円
ふつう3日ほどで確認が終わります。
9月1日(火)までに返事が来ます。
来なければ役場(0930-00-0002)へ。
支払いまち
町体育館
9月12日(土) 午前 9:00–12:00 / 1,200円
9月7日(月)までに払うと確定します。
払わないと自動で取り消されます(そのときもお金はかかりません)。
確定
町体育館
9月12日(土) 午前 9:00–12:00 / 1,200円/支払済
9月5日(土)まで無料で取り消せます。
9月6日(日)からは半額、9月9日(水)からは全額かかります。

ここが、いちばん最初の声への答えです。 「本人確認の完了まで時間がかかります」を電話で聞かされた人が困ったのは、待たされたことそのものではなく、 待っていることが画面のどこにも書いていなかったことだと考えました。 だから、審査という段を無くして隠すのではなく、段を画面に出して、いつ終わるかを本人に言う形にしています。

正直に書いておきます。この見本は本人確認そのものは扱っていません(個人情報を持たないと決めた見本なので、身元を確認する仕組みがありません)。 裏返せたのは「待っている状態を画面に出す」ところまでです。 ただし、卓球をしたい人が登録を求められずに空き表にたどり着いて、そのまま押さえられる—— もう一つの困りごとのほうは、仕組みごと消しました。

要らない説明は書かず、要る説明はその瞬間に出す

「押さえる」を押すと、そこで初めて呼び名を聞きます。先回りで利用者登録をさせません。 役場の確認が要る施設なら、その瞬間に「町体育館は、使い方を役場が確認します。押さえたあと、ふつう3日ほどで返事が来ます」と出ます。 前提を先に読ませるのではなく、前提が要る瞬間に、理由と一緒に出す——これだけです。

4. 担当が1人でも回るのか

よろず町は人口約3万人、役場の職員は150人で、情報システムの担当は1人の兼務、という設定にしています。 現実の町の多くがこの規模だからです。

この作りで、役場側の作業は増えません。増えるのは「取消の期限の規則を、施設ごとに表で持つ」ことだけです。 そしてそれは、今もPDFに書いてある内容をそのまま表にするだけ。 締切の種類が8通りあっても、施設群ごとに「取り消せる締切」「無料の線」「半額の線」の3列を持てば書けます。

PDFを更新する手間が、表を更新する手間に置き換わります。増えるのではなく、置き換わります。

5. しくみ(月0円で動きます)

置き場所Cloudflare Workers(1つ)。静的ファイルもAPIも同じ Worker が返す
データD1(SQLite)。施設5つと予約だけ
費用人口3万人の町の規模なら無料枠に収まります。超えても Workers Paid が月$5
デプロイwrangler deploy 1回
ライセンスMIT。自由にお使いください
技術の細部(設計のうえで効いた3点)

① 暦は必ず日本時間で切る。「9月6日まで無料」を UTC で判定すると、9月6日の朝9時に半額へ変わります。 この1点だけは、テストで固定してあります。

② 二重予約は、確かめてから書かない。D1 には「読んで→空きを確かめて→書く」を囲むトランザクションがありません。 代わりに部分ユニークインデックスを置き、入れてみて弾かれたら埋まっていたと読みます。

CREATE UNIQUE INDEX yorozu_booking_slot
  ON yorozu_booking (facility_id, date, slot)
  WHERE state IN ('checking', 'paying', 'confirmed');

弾かれたら「たったいま、ほかの人が押さえました」と返します。隙間で二重に入る余地が無いのはこの形だけです。

③ 期限は、押さえた瞬間に決めて予約自身に持たせる。あとから規則を読み直して計算しません。 規則が変わっても、既に押さえた人の約束は押さえた日の規則のまま動くほうが正しいからです。

AI に作らせてみたい人へ(非エンジニア向け)

この見本は、設計の条件を先に文章で固めてから、AI に書かせています。順番はこうでした。

  1. 既存のものを実際に触る。ここを飛ばすと、想像した分かりにくさを直すことになります。3つ触って、初めて「型」が見えました。
  2. 「何が分かりにくいか」を型として書き出す。上の5つがそれです。これがそのまま設計の指示書になります。
  3. ひとつずつ裏返す。「凡例を置かない」「白いマスを作らない」のように、やらないことで書くと AI に伝わりやすい。
  4. 計算だけはテストで留める。取消の期限のような「間違っても画面上は正しく見える」ところだけ、テストを書きました。画面の見た目は、実際に触って直すほうが早い。

6. どこまでが本当か

7. 自由にお使いください

しくみは MIT ライセンスで公開しています。参考にして各自で導入していただいて構いません。 導入のお手伝いや保守は、この研究所ではお約束していません。

「うちの町ではこう困っている」「ここは違うと思う」がありましたら、 ご意見・ご相談は投稿箱へどうぞ。お名前もメールアドレスもいただきません。

ともりの困りごと研究所/よろず町 第一号・生涯学習課「公共施設の予約」