ShutterPactが「ツール」から「小さなプラットフォーム」になるまで
前回の記事を書いたのが2026年7月4日、ShutterPactがv1.4.1だったころだ。あれから3週間、今日時点でv1.20.0になっている。
バージョン番号だけ見ると「細かい改善を積み重ねただけ」に見えるかもしれないが、実際に起きたのは、単発のルール生成ツールがコンテスト運営の一連の流れ(告知→応募受付→審査→結果発表→通知)を横断的に支える小さなプラットフォームへと形を変えたことだ。今日はその変化の過程を書いておきたい。
そもそも何を解決したかったのか
ShutterPactは、VRChatをはじめとするVR SNSのフォトコンテスト主催者向けに作ったツールだ。VRChatを知らない人向けに簡単に説明すると、VR空間上のアバターやワールドを撮影するVRフォトと呼ばれる文化があり、気持ちさえあれば誰でもフォトコンテストを主催できるコミュニティになっている。
問題は、その「気軽さ」の裏返しとして、ルールの明文化が主催者ごとにまちまちだったことだ。Unityでの撮影は許可されているのか。調整・加工はどこまで許されるのか。AIツールを使った加工はどこまで認められるのか。こうした点が曖昧なまま運営され、参加者の間でトラブルになるケースが実際にあった。
ShutterPactは、この曖昧さを解消するためのルール文書生成ツールとして始まった。ここまでは前回・前々回の記事に書いた通りだ。
フェーズ2: 「共有」と「発表」
v1.4の時点でも、ルールカードの共有リンク機能はあった。URLをコピーするだけで同じ文書を誰とでも共同編集できる仕組みで、当初は認証不要・リンクを知っている人は誰でも編集可能という利便性を優先した信頼モデルを採用していた。
これに加えて結果発表カードを追加した。募集カードと対になる「受賞者発表用カード」で、賞名・受賞者名・作品タイトル・写真・作家コメントや審査員コメントを載せてPNGまたはMarkdownで出力できる。受賞作品の写真は端末内で縮小・保存するだけでサーバーには一切アップロードしない。募集カードのときから貫いてきた「クライアント完結」の思想をそのままここにも引き継いだ形だ。
告知して終わりではなく、結果発表まで同じツールでカバーできるようになったのがこのフェーズの意味だ。
フェーズ3: 応募受付を引き受ける「ShutterPact-Submit」
ルール文書と結果発表カードが揃っても、実際の応募受付・審査・当選連絡という一番手間のかかる部分は主催者の手作業に残ったままだった。ここを支援するために作ったのが、姉妹アプリ「ShutterPact-Submit」だ。
ShutterPact本体とは別リポジトリ・別スタックで開発した。ShutterPact本体がサーバーレスの静的SPAであるのに対して、Submitは応募データを扱う以上、実際にサーバーとDBを持つ必要があったからだ。あと、リソースがめちゃくちゃ余ってた。そりゃもうすごい余ってた。
Submitでできることは以下の通りだ。
- 利用者はDiscordログインだけでコンテストを登録でき、応募の受付・審査(承認/却下)・CSV書き出しができる
- 共同管理者に「審査員(閲覧・審査コメントのみ)」「上位権限者(ルールカード編集権限まで持つ)」という2つのロールを設け、複数人での運営分担に対応した
- 承認済みの応募からShutterPact本体の結果発表カードへワンクリックでデータを取り込める。作品タイトル・名義・作家コメント・写真が自動で反映される
- 応募専用の「募集タイプ」として、審査なしで全作品を展示・共有する「企画展」、順位付けを伴わない「投票」も追加した。コンテストという枠を超えて、企画展示や人気投票のような用途にも対応範囲が広がった
告知・応募・審査・発表という一連の流れが、ここで初めてひとつながりになった。
フェーズ4: 一つのサービスとしての統合
Submitは当初 submit.mo4ca.net という別ドメインで動いていた。これを本体の shutterpact.mo4ca.net/submit/* 配下に統合したのが、直近でいちばん大きな変更だ。
同一オリジンになったことで、本体からSubmit側のログイン状態をサーバー間で照合できるようになった。これは単なる技術的な整理ではなく、実際にいくつかのセキュリティ・体験面の改善につながっている。
まず、共有リンクの新規発行にDiscordログインを必須化し、発行者IDを記録するようにした。これにより、他人の共有リンクを使って勝手に「主催者登録」してしまうような、コンテストの乗っ取りを防止できる。共有リンクの編集(PUT)にも認可チェックを追加し、作成者本人や上位権限者以外が保存しようとした場合は、元の文書を上書きせず新しい共有リンクとしてフォークする方式に変えた。元の文書を壊さないための設計だ。
露出経路そのものを増やす機能として、応募・投票へ直接進める「公開コンテストカレンダー」も新設した。主催者がオプトインしたコンテスト・企画展を締切順に一覧表示し、そこから読み取り専用のルール確認画面を経て応募・投票ページへ直接遷移できる。
細かい部分では、ShutterPactとSubmitで配色(デザイントークン)がずれていた問題を解消し、見た目の一貫性を統一した。表示テーマ(システム設定に合わせる/ライト/ダーク)も両サービス共通の考え方で実装している。
そして主催者向けに、Discordの個別通知(応募締切・結果発表・投票終了のリマインダー、応募者への審査結果通知、受賞者への当選通知)を追加した。これはBotと共有サーバーを持たなくてもDMを送れる「User-Installable Discord App」という手法を使っている。この実装では、認可URLの組み立て方ひとつでインストールが成立するかどうかが変わるという、ドキュメント化されていない仕様の落とし穴があった。実機で何度も試して、ようやく動く組み合わせを見つけた経緯がある。
一貫している設計思想
機能の幅は大きく広がったが、根底にある考え方は最初から変えていない。
主催者の負担を増やさない アカウント登録の強制や複雑な設定は避け、なりすましを防ぐ必要がある場面(共有リンク発行・主催者登録など)だけに認証を課す、段階的な信頼モデルを取っている。
参加者にとっての分かりやすさ ルールも結果発表も、文章の羅列ではなくカード形式の視覚的な出力にこだわっている。
プライバシー最優先のクライアント設計 受賞写真は端末内処理でサーバーを経由しない。解析にはCookieを使わないCloudflare Web Analyticsを使う。コア機能から一貫して、必要以上のデータを持たない設計を貫いている。ただし、オプトインでファイルアップロード機能も備えている。これはVRChatの展示ワールド等で扱うための用途を想定したものだ。Xと比べて圧縮もかからないので審査における画質面のメリットもある。
当事者性 自分自身がVRChatユーザーであり、このツール群の直接の利用対象者でもある。
今の状態
ShutterPact本体はv1.20.0、https://shutterpact.mo4ca.netで稼働している。ShutterPact-Submitは「オープンベータ」として一般公開済みで誰でも利用できる。
ヘッダーにBetaバッジ、ページタイトルに[BETA]が付いている。Submit連携・コンテストカレンダー・投票機能などは、バッジこそ付いているものの実際に動作している機能だ。正式公開の時期はまだ決めていない。
ルール作成→カレンダー掲載→応募受付→審査→結果発表カード作成→当選者へDiscord通知という一連の流れが今は一本の道になっている。
おわりに
最初は「ルールが曖昧で揉める」という、自分はVRフォトコンにあまり参加しないが、それでも周囲の声から感じた小さな不満から始まったツールだった。それが結果発表・応募受付・審査・通知へと自然に広がっていったのは、狙って設計したというより、実際に使いながら「次にここが足りない」と感じたものを順番に埋めていった結果だと思う。
今後もこのペースがずっと続くとは言わないが、まだ変えたいことはいくつもある。