← 森川裕基

event-form

天文サークルの観測会で、申し込みから当日の集金までを扱うアプリです。2025年10月から本番で動かしています。毎月の観測会で使っています。動かしたまま何度か作り直していて、いまの形になったのが2026年8月です。

会員のホーム、運営の名簿、当日の帳簿の3画面

何が面倒だったのか

観測会は夜に山へ行くので、車の乗り合わせが要ります。車を出せる人が何人いて、それぞれ何人乗せられるのか。送迎してほしい人のうち、誰が先に申し込んでいて優先されるべきなのか。宿泊の回なら、部屋数の上限もあります。

LINEの投票では、この順番がつけられません。毎回、乗せられる人数と申込順を確認して、乗り合わせを決めていました。その手間をなくすために作りました。

アプリがやるのは3つです。

申し込む

「現地集合/送迎してほしい/ドライバー」から選びます。集合場所を選ぶと送迎費が計算されて、当日払う額に加算されます。その時点で車の空席がなければ、「枠待ちでの申込になります」と申し込み前に表示されます。

申し込みの画面。参加方法と集合場所を選ぶ

名簿

集合場所ごとに、誰がどの車に乗るのかが並びます。席や定員を超えた人は理由付きで枠待ちに入り、空きが出たら「くり上げ」で確定します。

名簿の画面。集合場所ごとの参加者と枠待ちの一覧

帳簿

帳簿は1人につき1行です。出席か欠席かを選び、参加費を受け取ったらチェックします。ドライバーには送迎費を払います。全部の行を処理し終えると完了になります。

帳簿の画面。1行1人の点呼と集金

金額は自動で消さない

欠席にしても、金額は勝手に消えません。「徴収しない」を人が選んで、理由をメモに残します。お金の記録をアプリが勝手に書き換えないのは、このアプリで一番強く決めたルールです。

欠席を記録する画面。金額は自動では消えないという注意書きが出ている

作らない機能とその理由

要件書には、作らない機能とその理由を書いています。たとえば、掲示板はLINEグループを使っているので作りません。思いつきで機能を足さないために書き残しました。

Cloudflareの無料枠に合わせた設計

Cloudflare の無料枠で動かすので、できないことが多い。制約を回避するのではなく、制約に合う形を選びました。

時期ごとのデータの更新

受付中・締切後・当日以降で、書き込んでいい場所を分けています。受付中は本人が申し込み内容を記入し、締切後は運営だけが名簿を編集し、当日以降は帳簿だけを更新します。時期の切り替わりは全部時刻から自動で決まるので、運営が押すボタンは「イベントを作る」と「当日の帳簿」の2つで足ります。

構成

フロント
React 19 / TanStack Start(Router・Query・Form)/ Tailwind 4 / shadcn+Base UI
サーバ
Cloudflare Workers 1個 / Valibot
DB
Cloudflare D1(SQLite)/ drizzle ORM・21テーブル
認証
better-auth + LINEログイン + 管理者承認(4ロール)
連携
サークルのホームページ(WordPress)へイベントを自動掲載。プラグインも自作
テスト
vitest(判定ロジック等の単体18ファイル)+ Playwright(業務フローの E2E 5本)
運用
GitHub と連携した自動デプロイ。重要な操作は変更前後つきで監査ログに残す(29種)

アプリが使えなくなると翌日の観測会を運営できないので、障害対応もデータ移行も自分でやります。

掲載している画面のデータは紹介用に作った架空のもので、実際の会員の情報は含まれていません。