結婚式の招待状+引出物選択+受付システムを自作した話
はじめに
はじめまして。先日10月頭に結婚式を挙げました。
夫婦で楽曲、演出等、様々なこだわりポイントを詰め込んだわけですが、その中でも今回は「ゲスト向けフロントエンド」について話していこうと思います。
恥ずかしいのであまり具体的な画面はお見せできませんが…
尚、本記事の内容は
先駆者様[1]達に[2]多大な影響を受けております。
これらの方々の記事も素晴らしいのでぜひご一読ください!
経緯
自分の式を挙げるにあたり、情報収集を行っていたところ、近頃はWeb招待状が多いことを知りました。
そこで、いくつか無料Web招待状を調べてサンプルを見てみたのですが、、、
- デザインが気に入らない
- パフォーマンスが良くない。ページ読み込みに時間かかったり表示崩れたりすることがある
- 無料サイトにゲスト数十名分の個人情報を渡すのが怖い
等の課題点がありました。
もちろん私のリサーチ不足かもしれませんが、パッと調べた限りでは私が完全に気に入るサイトはございませんでした。
このことから、「どうせないなら作っちゃおう!自分のITエンジニアという職業もアピールできるし」と思い、自作することに決めました。
制作物概要
最終的に以下の3つのサイトを作りました。
- ゲスト向けフロントエンド
- 結婚式招待状
- 引出物選択
- 当日受付
- 管理者用フロントエンド
- URL発行
- ゲスト情報登録(名前、お車代、個々人へのメッセージ、座席)
- 引出物一覧登録
- ゲスト情報確認(出欠、アレルギー、備考、引出物)
- 当日受付用フロントエンド
- ゲスト向けフロントエンドと連携し、当日受付を行う
以下に主要な技術について話していきます。
フロントエンド
Next.js 15.5(App Router)
ゲストの方々に使ってもらうので、手慣れた技術を選択。
shadcn/ui
Tailwindで好きなようにガリガリスタイリングできるのが嬉しい。あと手慣れている
一部Acernity UIなどのshadcnライクなコンポーネントも採用
motion
- スクロールに合わせてフワッと動くアニメーションならこれで十分
- あんまりアニメのライブラリ増やすと表示崩れとかバンドルサイズ増大が怖い
ので、これ一本にした
その他
Valibot
- 個人的にzodより好みなバリデーションライブラリ。pipe記法が書きやすい
React Hook Form
- フォームライブラリで手慣れてたので、、、特に深い意図なし
バックエンド
Drizzle
TypeScriptでDB定義が完結するのが嬉しい。後手慣れてる
生のSQLに(比較的)近めにかけるところも良い
Hono
軽いしすぐ捨てられるしミドルウェアとRPC機能が優秀すぎる!!!
このライブラリがあるからフルTSを辞められない
その他
uuidv7
色々論争はありますが個人的にDB採番はuuidv7が一番好みなので、、、
ネイティブで採番してくれるDB知らないからマニュアル採番になってしまってる
jose
JWT認証用に。
認証周り
わざわざゲストの方々にログインの手間をとって欲しくありませんでした。
そのため、Next.js Middlewareで、
- 認証情報がCookieになければ認証用エンドポイントにリダイレクトし、「認証してね」という文言を出す
- /auth?token={トークン}で招待トークンを受け取り、バックエンドで認証→通ればhttponlyのcookieにセッショントークンを保存。uidの消えたページにリダイレクトする。
という処理を挟んでいます。
フロント→バックの通信では、セッショントークンをHono Middlewareで認証しています
インフラ、その他
Cloudflare(Workers, Durable Objects)
無料で10万リクエスト/日はすごすぎる。10msのコンピュート時間制限はあるけど、I/O時間は計算外だし。
今回に限らず色んなプロジェクトでお世話になってます
フロントはOpenNEXTを用いてWorkersにデプロイ
バックは基本的にはWorkers、受付のようなリアルタイム通信が必要な部分だけDurable Objectsにデプロイ
Turborepo
これもフルTSを辞められない理由の一つ。コマンド一つでビルドもデプロイもできるし、キャッシュ機能も偉すぎる。
モノレポ最高
Biome
自分はリント、フォーマットにあんまこだわりないのでとりあえずデフォ設定で使ってる。
Bun+Proto
Proto
ProtoでBunの環境管理してる。nodeもuvも色々使えるし、GitHub Actionsも便利だしお気に入り。
仕事ではmiseも使ってるけど、今回は複雑なコマンド管理とかないし、Protoで十分かな。使用感はほぼ変わらん
Bun
少々依存解決周りに癖があるけど、圧倒的に速い。それだけで選んでいる
(もちろん特有の問題もよく引くから、pnpmが良いのかな~とも思ったり)
力を入れたこと
デザイン
あらゆる媒体を検索して、自分が良いと感じたデザインの言語化に取り組みました。
その良いデザインのエッセンスの50%くらいは実現できたかな~と思います
友人にも「『エンジニアが作った画面』感なくてオシャレだね」と言ってもらえて嬉しかったです
デザインには最近流行ってる(?)モバイル・PC共通デザインパターンを使用しました。
お陰でスマホ向けデザインにのみ集中することができました
こういうやつ[3]です
受付QR表示機能
受付が紙の芳名帳だと、受付の方の負担が高いです。
- 座席案内
- 文字を書く手間
- お車代が必要かの照合
せっかく招待状でDBにゲストの情報を登録しているのだから、その情報を活用しよう!と考え、受付QR表示機能の追加開発に取り組みました。(当初は予定になかった)
受付システムでQRを読み込み、
- ご祝儀受け取り
- (必要な方のみ)お車代お渡し
を行い、受付完了すると、リアルタイムでQR画面が更新され、座席情報が表示されます。
この部分だけDurable Objectsを用いてWebsocket通信を確立しています
パフォーマンス改善
- PPRの採用
- Server ComponentsでPrefetch徹底
- Local FontsにしてGoogle FontsへのI/O時間短縮
- これはフォントによるかも、、、自分は改善したけど重いフォントだとしなさそう
- 画像の圧縮
- ほんとはavifにしたかったけど非対応ブラウザとか怖いからwebpに、、、
- Cloudflare Cacheのフル活用
まとめ
当日、ゲストの皆様から非常に良い反応をいただけました。
「クオリティ高くて売り物のサービス使ってるかと思った」などの嬉しいコメントも頂け、準備頑張って良かったな~としみじみと感じます。
式場のチーフの方が「これは当ホテルでも初めてのことですが、、、」と受付担当の方に説明を行われていてちょっと面白かったです。
これだけのシステムが全部無料でデプロイできるので、Cloudflare最強!!!!と改めて感じました。
一層信仰心が深まりました
Discussion