Skip to content

Latest commit

 

History

6 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 

Repository files navigation

🍺 Kanpai Lock

幹事を「仕事」から「楽しみ」へ。 飲み会の集金・割り勘・日程調整をワンストップで管理するフルスタックWebアプリ/ネイティブアプリ。

Next.js TypeScript Firebase Capacitor LINE LIFF Commits Lines


📌 概要

「幹事が一番楽しめない」という当たり前を変えるために、学生起業として0から企画・設計・開発しました。

飲み会幹事の3大作業(名簿管理・集金確認・未払い催促)をテクノロジーで自動化し、幹事も参加者と同じように場を楽しめる世界を目指しています。

🌐 Web版 kanpai-lock.com — インストール不要、LINEからそのまま起動
📱 iOS App App Store(Capacitor製ネイティブアプリ)
開発体制 チーム(企画/広報 + 設計/開発)、設計と実装を全て自分が担当

📂 ソースコードは非公開リポジトリで管理しています。閲覧をご希望の方は kanpailock@gmail.com までお気軽にご連絡ください。


✨ 主な機能

💰 集金・割り勘管理

機能 詳細
リアルタイム支払い管理 Firestoreリアルタイムリスナーで参加者全員の支払い状況を即時同期
傾斜割り勘計算 役割ごとの重み付けで不均等な割り勘を自動計算(幹事/一般/固定金額など)
PayPayリンク連携 URLを共有するだけで現金不要の即時集金
自動精算通知 精算開始時にLINE or FCMプッシュ通知を全員に自動送信
未払い自動リマインド Cloud Functionsのスケジュールトリガーで毎日18時に未払い者へ自動催促

🎪 パーティ管理

機能 詳細
n次会(複数ラウンド)対応 途中参加・抜けに応じてラウンドごとに参加者と金額を独立管理
定員管理 満員時の自動ブロック・定員オーバー通知
LINEグループ一括取込 LINEのグループメンバーをAPIでインポートし事前登録
日程調整モード ○△× 投票 + スコア自動集計でベスト日程をランキング表示
リアルタイムチャット 日程調整中のメッセージング機能

🔐 認証・UX

機能 詳細
マルチ認証 LINE LIFF / Google / Apple Sign-In の3プロバイダ対応
DeepLink URLパラメータでルームIDを共有・直接参加、ブラウザ→アプリ連携
オフライン対応 ネットワーク切断時もUIを維持し、復帰時に自動再接続

🏗 技術的な工夫とチャレンジ

1. iOS ネイティブ環境における Firebase JS SDK の制約回避

課題: Capacitor の WKWebView 環境では、Firebase JS SDK の setDoc / getDocハングする問題が発生。

解決策: ネイティブ環境では Firestore REST API 経由でデータアクセスするアダプタ層 (nativeFirestore.ts) を設計。isNativeEnvironment() でランタイム判定してWeb/ネイティブを自動分岐。

// 環境に応じて透過的に使い分けられるAPI設計
export async function getDocNative(collectionPath, docId) {
  if (isNativeEnvironment()) {
    return await firestoreRestGet(collectionPath, docId);  // REST API
  }
  return await getDoc(doc(db, collectionPath, docId));      // JS SDK
}

🎯 学び: クロスプラットフォーム開発では、SDK が「動かない」ケースを想定したフォールバック設計が重要。


2. Apple Sign-In のカスタム Swift プラグイン実装

課題: Capacitor の Apple Sign-In プラグインでは idTokennonce を直接取得できず、Firebase 認証の OAuthCredential を生成できない。

解決策: カスタム Swift プラグインを自作し、ASAuthorizationController で直接 Apple 認証を実行。SHA256 nonce を生成してFirebase に渡す一連の処理をネイティブコードで実装。

🎯 学び: プラグインの既存API に依存せず、ネイティブコードまで降りて問題解決する経験。


3. 参加記録の二重保存アーキテクチャ

課題: participants[userId] のみに依存すると、Firestore書き込み失敗時にユーザーがルームを見失う。

解決策: ユーザープロフィール (users/{uid}/profile) にも joinedRooms として参加記録を保存する二重保存設計を採用。再アクセス時にフォールバックとして自動復帰可能。

[ルームデータ]                    [ユーザープロフィール]
rooms/{roomId}                   users/{uid}/profile
  └── participants/{uid}     ←→    └── joinedRooms/{roomId}
        (正データ)                       (フォールバック)

🎯 学び: 分散システムにおけるデータ整合性と可用性のトレードオフを実践で体得。


4. iOS 認証状態復元の高速化

課題: Firebase onAuthStateChanged はWeb用設計のため、iOSネイティブでは認証復元に1-2秒かかり、ユーザーがログイン画面にフラッシュバックする。

解決策: onAuthStateChanged を待たず、iOS Keychain からネイティブ SDK で即座にユーザー情報を復元する tryEarlyNativeAuth() パターンを実装。Web版は800ms、iOS版は1500msのフォールバックタイマーを設定し、UXを損なわない。

[起動]
  ├── tryEarlyNativeAuth()     ← iOS: Keychainから即座に復元
  ├── onAuthStateChanged()      ← Web: Firebase標準の認証復元
  └── setTimeout(fallback)     ← どちらも来なかったらログイン画面へ

🎯 学び: 体感速度のチューニングは数値(msオーダー)で管理し、プラットフォーム別に最適化する。


5. LINE × Firebase 認証の統合

課題: LINE LIFF で認証したユーザーと Firebase Authentication のユーザーIDは別物。同一ユーザーがLINEとGoogleで参加した場合の紐付けが複雑。

解決策: firebaseUid / lineUserId / linkedUserId の3属性を参加者データに持たせ、統合検索ヘルパー (findMyParticipantData) で全方向から自分を特定。LINEグループからインポートした事前登録メンバーとの紐付けもスムーズに処理。

🎯 学び: 複数認証プロバイダの統合は「IDの正規化」が鍵。設計を後から変えるとコスト大。


6. Firestore セキュリティルール設計

認証済みユーザーのみアクセス可能、幹事のみ削除可能、プロフィールはオーナーのみ R/W、LINEグループ情報は Cloud Functions (Admin SDK) からのみ書き込み可能——といったロールベースのアクセス制御を Firestore Security Rules で実装。


🛠 技術スタック

フロントエンド

技術 用途
Next.js 16 (App Router) ルーティング・SSR
TypeScript 5.9 型安全な開発(32,000+ 行)
Tailwind CSS 4 レスポンシブUI
React 19 コンポーネント設計(28カスタムフック)
Capacitor 8 Web → iOS/Android ネイティブラッパー
LINE LIFF SDK LINEミニアプリ統合

バックエンド

技術 用途
Firebase Firestore リアルタイムDB + セキュリティルール
Firebase Authentication LINE / Google / Apple 認証
Firebase Cloud Functions サーバーレスAPI(10ファイル / 95KB)
Firebase Cloud Messaging iOS/Webプッシュ通知
Vercel Webホスティング・CDN

iOS ネイティブ

技術 用途
Swift (カスタムプラグイン) Apple Sign-In 実装
APNs → FCM プッシュ通知チェーン
iOS Widget (WidgetKit) ホーム画面ウィジェット

品質管理

技術 用途
Vitest + Testing Library ユニットテスト
ESLint コード品質
Firestore Security Rules アクセス制御
Rate Limiting Cloud Functions API保護

📊 プロジェクト規模

指標 数値
総コミット数 1,228+
TypeScript総行数 32,000+ 行
Reactコンポーネント 46ファイル
カスタムフック 28個
ユーティリティ 24ファイル
Cloud Functions 10ファイル / 95KB
開発期間 約3ヶ月

� アーキテクチャ

[ユーザー]
    ├── Web (PWA / LINE LIFF)
    ├── iOS App (Capacitor)
    └── LINE Mini App
          │
          ▼
    ┌──────────────────────────────┐
    │  Next.js 16 / Vercel         │
    │  ├── App Router (SSR/CSR)    │
    │  ├── Components (46ファイル)  │
    │  │   ├── room/       精算UI  │
    │  │   ├── views/      画面    │
    │  │   ├── schedule/   日程    │
    │  │   └── modals/     モーダル│
    │  ├── Hooks (28個)            │
    │  │   ├── useAuthController   │
    │  │   ├── useRoomOperations   │
    │  │   ├── useSettlement       │
    │  │   └── useScheduleVoting   │
    │  └── Utils (24個)            │
    │      ├── nativeFirestore     │
    │      ├── nativeAuth          │
    │      └── nativeStorage       │
    └──────────┬───────────────────┘
               │
    ┌──────────▼───────────────────┐
    │  Firebase                     │
    │  ├── Firestore (リアルタイム) │
    │  ├── Authentication           │
    │  │   ├── LINE (LIFF→Custom)  │
    │  │   ├── Google (OAuth)      │
    │  │   └── Apple (Swift)       │
    │  ├── Cloud Functions          │
    │  │   ├── LINE Webhook        │
    │  │   ├── 自動リマインド通知   │
    │  │   ├── プッシュ通知         │
    │  │   └── レートリミット       │
    │  └── Cloud Messaging (FCM)   │
    └──────────────────────────────┘

📂 ディレクトリ構成

kanpai-lock/
├── app/                    # Next.js App Router
│   ├── page.tsx            # メインSPA (8.6KB)
│   ├── layout.tsx          # レイアウト・メタデータ
│   ├── payment/            # 支払いページ
│   └── privacy/, terms/    # 法務ページ
├── components/             # Reactコンポーネント (46ファイル)
│   ├── KanpaiUI.tsx        # メインUIコントローラ (14KB)
│   ├── LandingPage.tsx     # LP兼ログイン画面 (45KB)
│   ├── room/               # 部屋管理UI (26ファイル)
│   ├── views/              # 画面コンポーネント
│   ├── schedule/           # 日程調整UI
│   └── modals/             # モーダル群
├── hooks/                  # カスタムReactフック (28個)
│   ├── useAuthController   # 認証制御 (799行)
│   ├── useRoomOperations   # ルーム操作 (577行)
│   ├── useSettlement       # 精算ロジック
│   └── useScheduleVoting   # 日程調整投票 (410行)
├── utils/                  # ユーティリティ (24ファイル)
│   ├── nativeFirestore.ts  # iOS環境分岐アダプタ
│   ├── nativeAuth.ts       # 認証環境分岐
│   └── kanpaiUtils.ts      # ビジネスロジック
├── functions/              # Cloud Functions
│   └── src/
│       ├── lineHandlers.ts    # LINE Webhook (29KB)
│       ├── notifications.ts   # LINE通知 (20KB)
│       ├── pushNotifications.ts # FCM通知 (17KB)
│       ├── auth.ts            # カスタム認証
│       └── rateLimit.ts       # レートリミット
├── ios/                    # Capacitor iOSプロジェクト
├── android/                # Capacitor Androidプロジェクト
├── __tests__/              # テストスイート
├── firestore.rules         # セキュリティルール
└── locales/                # i18n (ja/en)

🚀 ローカル環境での起動

# 依存パッケージのインストール
npm install

# 環境変数を設定
cp .env.local.example .env.local
# Firebase / LINE API キーを設定

# 開発サーバー起動
npm run dev

# テスト実行
npm run test:run

# iOS(要Xcode)
npx cap sync ios && npx cap open ios

🔒 セキュリティ設計

  • Firestore Security Rules: ロールベースアクセス制御(幹事のみ削除可、プロフィールはオーナーのみ)
  • Apple Sign-In: SHA256 nonce 検証をカスタム Swift プラグインで実装
  • Cloud Functions: レートリミットでAPI乱用を防止
  • 環境変数: Vercel / Firebase Secrets で管理、.env.local はGitignore済み
  • LINEグループ情報: Admin SDK(Cloud Functions)からのみ書き込み可能

👥 チーム

名前 役割 担当
関屋 Founder 企画・広報・マーケティング
上嶋 Developer 設計・開発・インフラ・テスト

Yohaku Lab © 2026

About

Party management app for organizers - bill splitting, payment tracking, and scheduling. Built with Next.js, TypeScript, Firebase, and Capacitor.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors