
こんにちは、Procom開発者の海老氏です。
今日は**SNS連携型プロフィールプラットフォーム「Procom」の開発において、「ユーザー写真アップロード&スライダー表示機能」をNext.js×Firebase(Storage)**で実装した進捗について、4000文字超で赤裸々に綴ります。
この機能は、「自分の活動や世界観を最大5枚の写真でアピールできる」という、Procomの“顔”ともいえるUI。YouTubeやInstagram連携などSNS部分も重要ですが、クリエイターやフリーランスにとって**“見せるプロフィール”**は自己ブランディングの命です。
そんな思いを込めつつ、実装の苦労や解決策、成長の記録をすべて残します。
Contents
■ なぜ写真スライダー&アップロード機能が重要なのか?
現代のSNSは「自己紹介文」だけでなく、「写真・ビジュアル」がコミュニケーションの主役です。
特にProcomのターゲットであるYouTuber、ダンサー、パフォーマー、フリー芸人などは、ビジュアルで一瞬にして世界観や個性を伝えたい。
そのため「最大5枚まで」「簡単にアップロード」「スライダーで魅せる」ことが欠かせません。
■ 技術的な課題:Next.js+Firebase時代の画像管理
これまではVanilla JSとFirebase(Firestore/Storage)で実装してきたが、**Next.js(App Router構成)**に移行したことで課題が山積み。
- クライアント(React)でファイル選択→APIでサーバー側に送る仕組み
- Next.jsのApp RouterでのAPI設計(/api/uploadPhotos)
- Firebase Storageへの画像アップロードと公開URL取得
- StorageとFirestoreの整合性管理
とくに画像のバリデーションや同時アップロード、即時プレビュー更新など「使いやすさ」と「セキュリティ」「パフォーマンス」のバランスが問われました。
■ 実装ステップ:親子コンポーネント分割で責任範囲を明確に
まずReactの設計方針として、
- PhotoSliderBlock(親)…ファイル選択・保存UI+画像配列の管理
- PhotoSlider(子)…画像スライダー本体(object-position調整も)
というようにコンポーネント分割。
この分割が地味に大事で、「アップロード後の状態管理」や「スライダーのobject-position(画像表示位置)調整」をシンプルにできます。
■ コードで解説!画像アップロード~表示までの全体フロー
1. ファイル選択+保存UIの設置(PhotoSliderBlock)
tsxコピーする編集する<form onSubmit={handleUpload}>
<input
type="file"
accept="image/*"
multiple
max={5}
onChange={e => setSelectedFiles(e.target.files)}
/>
<button type="submit" disabled={!selectedFiles}>保存</button>
</form>
選択した画像(最大5枚)はFormDataでサーバーAPI(/api/uploadPhotos)にPOST。
ここで「即時プレビュー」を実装することも考えましたが、「Storageで保存されたURLでのみスライダー表示」と割り切ることで同期の一貫性を確保。
2. サーバーAPI(/api/uploadPhotos)でFirebase Storage保存
Next.jsのAPI Routeで、
- FormDataから画像ファイルとuidを受け取る
- Buffer化してStorageの
users/{uid}/photos/{uuid}.jpgに保存 - 公開URL生成(バケットがpublicの場合)
- 必要ならFirestoreのユーザードキュメントにURL配列を反映
という「非同期アップロード+URL配信」パターン。
tsコピーする編集するfor (const file of files.slice(0, 5)) {
const buffer = Buffer.from(await file.arrayBuffer());
const filename = `users/${uid}/photos/${uuidv4()}.jpg`;
const fileRef = bucket.file(filename);
await fileRef.save(buffer, { contentType: file.type, public: true });
const url = `https://storage.googleapis.com/${bucket.name}/${filename}`;
urls.push(url);
}
アップロード後はURL配列をJSONで返し、フロントでスライダーを更新!
■ スライダーの設計とユーザー体験
スライダーUIは1枚目を中央に大きく、前後は斜め回転+半透明で表示するデザイン。
object-positionをrangeスライダーで微調整できるので、被写体の位置に合わせて写真を最適化できます。
このあたりはInstagramやTikTokのUIを徹底分析し、**“プロっぽく見せる体験”**を意識して設計しました。
■ 苦労したポイントとその乗り越え方
1. Next.js App RouterでのFormDataハンドリング
従来のExpressサーバーとは異なり、Next.jsのAPI RouteはFormData/Bufferの処理や型付けに若干クセがあります。
たとえばformData.getAll("photos")で配列取得し、型アサーションでFile型と明示することでエラーを回避。
また、開発環境・本番環境(Vercel/Render等)によってStorageバケットのパスや公開設定も異なるため、.env管理の徹底も大切だと再認識しました。
2. Firebase Storageの公開設定
アップロードした画像を誰でも見られるようにpublic設定を忘れると、URLを返しても「403 Forbidden」で見られないという罠。
Firebase ConsoleでStorageバケットの公開設定(allUsersの読み取り権限)やCORS設定も確認。
3. UIの“即時反映”とUXの両立
「アップロード直後にスライダーを即座に更新」するには、APIから返ってきたStorage URLでsetPhotosし直す必要があります。
バリデーション(最大5枚、画像のみなど)や保存中のローディング表示、エラー処理も徹底。
■ 今日学んだ技術的Tips
- Next.js×Firebaseでの画像アップロードAPI設計は「FormData→Buffer→Storage」が基本
- フロント側での
FileList管理やFormData.append()の使い方(multiple対応) - サーバー側でのStorage保存パス設計(
users/{uid}/photos/) - 公開URLの組み立て(Firebase Storageの場合、
https://storage.googleapis.com/{バケット名}/{パス}) - 画像スライダーの設計とobject-position調整UI
- アップロード処理のローディングUI、エラー制御
■ 今後の展望:よりプロフェッショナルなプロフィール体験へ
本日の開発で「Procomの顔」ともいえる写真スライダー+アップロード機能の第一歩が完成しました。
ですが、今後さらに以下の点を強化したいと考えています。
- Firestoreとの連携強化
写真URL+object-positionをFirestoreに保存し、ページ再表示時も“同じ位置・同じ並び”で再現する。 - 画像の削除・並び替え対応
UIから「この写真を削除」「並び順を変更」できるようにし、より柔軟なプロフィール編集を実現。 - アップロード画像の圧縮・最適化
モバイル回線でも軽快に表示できるように、アップロード前の画像リサイズ&圧縮処理を導入予定。 - ドラッグ&ドロップ対応UI
スマホやタブレットからも直感的に画像を追加できるUXへ。 - プライバシーやセキュリティ対策
Storageのアクセス制御やファイル名衝突、ストレージの課金対策も視野に入れて進める。
■ まとめ:小さな進捗の積み重ねが未来をつくる
今回の写真アップロード&スライダー実装は、一見シンプルに見えますが、
- 「どのタイミングでAPIを呼ぶべきか」
- 「アップロードと同時にスライダー表示をどう実現するか」
- 「Firebase Storageのpublic設定やセキュリティ」
- 「UI/UXの細やかな設計」
など、考えることは山ほどありました。
でも、ひとつずつ設計を整理し、**「何のためにこの機能を作るのか」**を自分の中で明確にすることで、迷わず進むことができました。
最後に…
このブログをここまで読んでくれた方、本当にありがとうございます。
Procomはまだまだ発展途上ですが、**「すべてのクリエイター・フリーランスが主役になれる場所」**を目指して、日々“細かな工夫と挑戦”を積み重ねています。
技術的な質問や感想、アイディアなど、コメント・DMでお気軽にご連絡ください!
引き続き、明日も成長あるのみ。コツコツやっていきます。









