文化祭やイベント向けのリアルタイムウェブアプリを作ってみた
SupabaseとNext.jsを活用し、文化祭の模擬店混雑状況やイベント進行をリアルタイム共有するOSSアプリを作った
Intro
文化祭では、多くのステージ企画、模擬店、展示がキャンパスのあちこちで同時に動いています。「今どの模擬店が空いているのか」「次のバスはいつ来るのか」「落とし物は届いていないか」といった情報を1つにまとめた汎用リアルタイムWebアプリフレームワークFesTimeを開発しました。
このアプリはApache 2.0ライセンスでオープンソースとして公開しており、どの学校やイベントでも導入可能なシステムになっています。
アプリの主な機能
本アプリは、単なる情報の羅列ではなく、“今どうなっているか” を現地に行かなくても即座に把握できることを目的にしています。
- 模擬店のリアルタイム状況: 各模擬店の混雑度と在庫状況を「緑・黄・赤」の信号機形式で一覧表示
- インタラクティブマップと現在地連動: 校舎内に配置されたQRコードを読み取ると、現在地周辺の模擬店や展示をハイライト
- リアルタイム・ニュース配信: 運営からの重要告知をリアルタイムにプッシュ配信
- タイムテーブル・バス時刻表: 直近のイベント進行度や、現在時刻から乗れる直近のシャトルバスを自動算出
- 写真付き落とし物リスト: 画像付きで落とし物を即時公開(通信量配慮のため画像表示は切り替え可能)
- 匿名Q&A掲示板: 一般ユーザーと運営チームが直接やり取りできる機能
- オンライン投票: 多重投票を防止しつつ、模擬店や展示のリアルタイム投票・集計が可能
- 権限管理: 運営・出店団体・一般ユーザーとロールを分け、店舗側はシフト引き継ぎをセキュアなQRコードで行える仕組み
技術スタックと課題
FesTimeは以下のモダンなWeb技術をベースに構築されています。
| 分野 | 技術・ツール |
|---|---|
| フロントエンド | Next.js 15 (App Router / Static Export), React 19, TypeScript |
| スタイリング & UI | Ant Design, Material UI Icons, Framer Motion |
| バックエンド / BaaS | Supabase (Database, Auth, Realtime) |
| インフラ | GitHub Pages |
最大の壁: トラフィック制限との戦い
開発にあたって最も困難だったのは通信量の削減です。
Supabaseの無料枠(Free Plan)には、月間5GBまでのデータ通信量制限と、Realtime(WebSocket)の同時接続数最大200人という厳しい制約があります。 模擬店の状態更新やニュース配信などをJSON形式でそのまま全クライアントにブロードキャストすると、あっという間にトラフィック制限を超過してしまいます。また、200人を超えると新しいクライアントにはリアルタイム更新が届かなくなります。
問題解消アプローチ
これらを回避・軽減するために以下のアプローチを取りました。
-
ペイロードの極限圧縮 通信に使うJSONのキーを1文字(
id→i,status→sなど)に短縮し、送信する内容も必要最小限に留めました。テキストデータの代わりにUIDを活用することで、通信量を当初の30%まで削減することに成功しました。 -
静的データと動的データの分離 開催前から確定しているステージ企画のタイムスケジュールや、バスの運行スケジュールについてはSupabaseに置かず、JSONファイルとしてGitHub Pages上にデプロイしました。これにより、Supabaseとの通信は「開催中にリアルタイムで変動するデータ(混雑状況やニュースなど)」だけに絞り込むことができました。
-
厳格なセキュリティとテスト 模擬店の状態変更や投票機能に対する悪意のあるアタックは、イベントの売上や公平性にクリティカルな影響をもたらします。SupabaseのRLS (Row Level Security) によって書き込み権限を厳密に制限しました。 開発期間の半分をこの安定性・セキュリティテストに費やし、完成後には「自分が極悪人になったつもり」で全機能へのアタックコードを書き、脆弱性がないかを徹底的に検証しました。
実際の運用実績 (第18回 北斗祭)
FesTimeは、もともと2026年に開催された「第18回 北斗祭」のためだけに開発したシステムを、汎用的なフレームワークとして再構築したものです。 北斗祭では当日にどれくらいのアクセスが来るか未知数だったため、開催月のみSupabaseのProプランにアップグレードして無料枠制限を回避しました。
実際の使用実績は以下の通りです。
| 項目 | 数値 |
|---|---|
| ユーザー数 | 1,385人 |
| PV数 | 9,060 |
| リアルタイム通信数 | 14,987回 |
| データベース通信数 | 25,400回 |
今後の課題とアップデート案
実際の文化祭で運用してみて、いくつかの気づきと新たな課題が見えてきました。
-
課題1: 忙しい模擬店は更新する暇がない 本当に混雑している人気店ほど、忙しすぎてアプリ上の「混雑度」を更新する余裕がなくなります。
- 解決案: 来場者が混雑状況を報告できるようにする。
- 懸念点: いたずらや悪意のある偏った報告が発生する可能性があるため、そのフィルタリング機構が必要。
-
課題2: 固定スケジュールも実は変動する バスやステージ企画は静的ファイルとして切り出しましたが、当日の進行状況や座席状況によっては時間が押したり早まったりと変動します。
- 解決案: 変動の可能性があるものはすべてSupabase経由で編集可能にする。
- 懸念点: 基本的には中身が変わらない内容のためにトラフィックを消費することになり、無料枠運用では通信量の無駄遣いが発生する。
Outro
もともとReactでいくつかのWebアプリを作っていた経験から、コンポーネントの流用によりUIの開発自体はサクサクと進められました。しかし、不特定多数のユーザーが同時にアクセスし、さらに悪意のある操作も想定しなければならない公共イベント向けアプリでは、「インフラの制限」と「セキュリティ」がいかに重要かを学ぶ良い経験になりました。
FesTimeはOSSとして公開しています。
- この内容のWebアプリ: FesTime
- この内容のリポジトリ: GitHub - rsu-Suba/FesTime