40
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【個人開発】泳げば泳ぐほどモテる。水泳×マッチングアプリ「スイモテ」を作りました【React × Supabase × Firebase】

40
Last updated at Posted at 2026-04-05

⚠️ 本サービスは開発中のポートフォリオ作品であり、一般ユーザー向けには公開しておりません。
マッチングアプリとして実運用する際には、出会い系サイト規制法に基づく届出・年齢確認等の法的対応が必要です。

はじめに

「マッチングアプリ疲れ」という言葉を最近よく聞きます。

プロフィールを盛って、いいねを送って、メッセージを続けて——それでも会えるかわからない。既存のマッチングアプリは自己申告ベースなので、「本当にアクティブな人なのか」が見えません。

一方で、水泳の練習記録アプリは世の中にいくつかあります。ただ、記録するだけだと続かない。モチベーションが保てない。

「記録アプリだけだと続かない。マッチングアプリだけだと疲れる。じゃあ融合させたら?」

そう考えて作ったのが スイモテ(Suimote) です。


コンセプト

泳げば泳ぐほどモテる

スイモテ = 「すいすいモテる」。名前にコンセプトが全部詰まっています。

  • 練習記録 = マッチングのプロフィール
  • 泳いだ距離・回数が「本気度の証明」になる
  • プロフィールを盛る必要がない
  • 出会いの場がプール・ナイトプール

ユーザー価値

ユーザー   価値
男性 練習記録がそのまま「本気度の証明」。プロフィールを盛る必要がない
女性 まず記録アプリとして使える。マッチングはオプトインで後からONにできる
両方 共通の趣味・活動実績ベースでつながる。「マッチングアプリ疲れ」の回答

アーキテクチャ

アーキテクチャ図


デモ

1. 練習記録のCRUD(追加 → 一覧 → 編集 → 削除)

NO.1 (2).gif

2. プロフィール編集 → マッチングON

NO.2.gif

3. ユーザー一覧 → いいね → マッチ成立

NO.3.gif

4. マッチ一覧 → 相手のプロフィール

NO.4.gif


技術選定

なぜReact(TypeScript)?

  • コンポーネント指向でUI部品を再利用しやすい
  • TypeScriptで型安全。DBのテーブル定義と型を一致させることでバグを防げる
  • エコシステムが豊富(React Router, Jest, shadcn/ui)

なぜSupabase?

  • PostgreSQLベースで、RLS(行レベルセキュリティ)が使える → 「自分のデータは自分だけ」をDB層で保証
  • RPC関数でサーバー側計算 → 累計距離・月間回数をDB側で集計して返す
  • リアルタイム機能やStorageも標準装備 → v2のDM機能に拡張可能

なぜFirebase Hosting?

  • 無料枠が十分
  • GitHub Actionsとの連携が簡単
  • CDNで配信されるので表示が速い

なぜGitHub Actions?

  • pushするだけで lint → test → build → deploy が自動実行
  • テストが落ちたらデプロイされない = 安全網

設計判断

1. エリアベースのマッチング

施設単位ではなく、首都圏を12エリア(渋谷・新宿、池袋・板橋など)に分割。

  • 施設単位だと母数が少なすぎる問題を解決
  • 同じエリアのプールに通う人同士なら「会いやすい」

2. オプトイン方式

マッチング機能はデフォルトOFF。ユーザーが自分でONにして初めて有効化。

  • 女性ユーザーの心理的ハードルを下げる
  • 「記録アプリだと思って入れたら、出会いの機能もあった」という自然な導線
  • 記録アプリとしてだけ使い続けることも可能

3. 相互いいねでマッチ成立

一方的ないいねではマッチしない。お互いがいいねを送って初めてマッチ成立。

4. 段階的リリース(MVP戦略)

1ヶ月を7つのMVPに分割し、各フェーズで「テスト → CI/CD → 自動デプロイ」を完結。

フェーズ  内容 状態
MVP1-3 練習記録アプリとして先行リリース 完了
MVP4-5 マッチング機能をオプトインで後出し追加 完了
MVP6 全体動作確認・デザイン調整 完了
MVP7 技術記事・README整備 ← 今ここ

どのフェーズで時間切れになっても動くプロダクトが残る設計。


学び・気づき

テストは最強の味方

全機能に対して27のテストスイートを書いた。
内訳はUIコンポーネント14件、カスタムhooks10件、
ユーティリティ3件。
npm test を実行したら、4秒ですべてPASS

手動だと30分以上かかる確認が、コマンド1つで完了。
コードを変更するたびに「壊れてないか」を一瞬で検証できるのは、テストを書いてきたからこそ。

RLSの不備を通し確認で発見

MVP6の通し確認で、practice_records テーブルのRLSが無効(DISABLED)だったことを発見。ポリシーは作ってあったのにスイッチがOFFだった。

手動テストだけでは気づけなかったかもしれない。
DB側のセキュリティ確認は必ずやるべきと実感。

存在しないRPC関数の発見

get_monthly_practice_count 関数がDBに存在しないことも通し確認で判明。migrationファイルに書いていなかったため、Dashboardで手動作成したものが記録に残っていなかった。

migrationファイル = DBの変更履歴。
必ずセットで残す
ことの重要性を学んだ。


今後の展望(v2以降)

  • 位置情報 — 近くのプールにいる人をリアルタイムで表示
  • ナイトプールイベント連携 — 会場にいる人同士でマッチング
  • DM(チャット)機能 — Supabase Realtimeを利用
  • 練習実績バッジの拡充 — 累計距離・連続記録でランクアップ
  • 収益化 — イベントチケット販売・プレミアムプラン

技術スタック

カテゴリ 技術
フロントエンド React 19, TypeScript, Vite, Tailwind CSS, shadcn/ui
バックエンド/DB Supabase (PostgreSQL, Auth, Storage, RPC)
ホスティング Firebase Hosting
CI/CD GitHub Actions (lint → test → build → deploy)
テスト Jest, React Testing Library
アイコン Lucide React
フォント Geist

おわりに

「記録するだけ」のアプリは続かない。
「出会うだけ」のアプリは疲れる。

スイモテは 「泳いで、つながる」 という新しい体験を
提供するアプリです。

フィットネス記録とマッチングの融合は未開拓の領域。この記事が、同じように個人開発に挑戦する方の参考になれば幸いです!

40
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?