Skip to content

bearwash/project-encounter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Project Encounter

BLE による物理的すれ違いを再現する、位置情報非依存のアバターアプリ。

詳細は docs/要件定義.md を参照。


開発方針: 仕様駆動開発 (Spec-Driven Development)

実装の前に、機能ごとの仕様 (docs/specs/) と契約 (docs/contracts/) を確定させる。 コードはこの仕様への準拠物として扱い、仕様とコードが乖離した場合は 仕様を真実とみなして 修正方針を決める。

サイクル

  1. 要件docs/要件定義.md(プロダクト全体の合意)
  2. 仕様docs/specs/<feature>.md(機能単位の WHAT/HOW/受入基準)
  3. 契約docs/contracts/*(型・スキーマ・API。フロントとバックエンドの境界)
  4. 実装src/(Next.js / TypeScript) + src-tauri/(Rust)
  5. 検証 — 受入基準で確認 → 仕様 or 実装を更新

技術スタック

  • アプリ: Tauri v2 (macOS デスクトップ + iOS / Android)
  • UI: Next.js (App Router) + React + Tailwind CSS + @tanstack/react-query
  • コア: Rust (BLE: btleplug @ desktop、CoreBluetooth / Android Bluetooth は Tauri mobile plugin)
  • DB ローカル: SQLite (Tauri Plugin SQL)
  • DB クラウド: Supabase (Postgres + 匿名 Auth + RLS)
  • パッケージマネージャ: pnpm

セットアップ

0. 環境変数 (Supabase)

cp .env.example .env.local
# NEXT_PUBLIC_SUPABASE_URL / NEXT_PUBLIC_SUPABASE_ANON_KEY を埋める
# 未設定でも mock モード (Rust 側 profile_fetch_remote) で動作

Supabase 側のスキーマは docs/contracts/supabase-schema.sql を Studio SQL Editor に貼って実行。Authentication > Providers で Anonymous sign-ins を有効化

サーバーサイドの責務と、将来 Supabase 直結を API サーバーへ置き換える場合の契約は docs/specs/server-side.mddocs/contracts/server-api.md を参照。

ローカル契約検査:

pnpm server:check

サーバー側の実機不要 preflight:

pnpm server:preflight

Supabase 実プロジェクトの疎通確認:

NEXT_PUBLIC_SUPABASE_URL=... NEXT_PUBLIC_SUPABASE_ANON_KEY=... pnpm server:smoke

server:smoke は anonymous sign-in、プロフィール upsert / resolve / delete、RLS による他人プロフィール更新拒否、DB 制約による不正プロフィール拒否まで確認する。

1. 依存解決 / 整合チェック

pnpm install
pnpm typecheck
(cd src-tauri && cargo check)

2. 開発サーバ (デスクトップ / WebView)

pnpm dev          # ブラウザで http://localhost:1420 (UI のみ、SQLite なし)
pnpm tauri:dev    # Tauri WebView (デスクトップアプリ、SQLite + 実 BLE @ macOS)

3. iOS ビルド

# 初回のみ
pnpm tauri ios init       # Xcode プロジェクトを src-tauri/gen/apple に生成
                          # (cocoapods 必須: brew install cocoapods)

# 開発実行
pnpm tauri ios dev        # シミュレータで起動
pnpm tauri ios dev --host # 実機 (要 Apple Developer Team)

iOS 環境:

  • Xcode 15+ (現状 26.x で確認済)
  • rustup target: aarch64-apple-ios, aarch64-apple-ios-sim, x86_64-apple-ios
  • cocoapods (brew install cocoapods)
  • 実機ビルドには tauri.conf.json > bundle > iOS > developmentTeamAPPLE_DEVELOPMENT_TEAM env

src-tauri/gen/ は gitignore されるため、tauri ios init のたびに以下のスニペットを 手動マージ してください:

4. Android ビルド

Android Studio + SDK + NDK が要る。手順:

brew install --cask android-studio          # GUI でセットアップ完了させる
# Android Studio > More Actions > SDK Manager で:
#   - Android SDK (API 34 以上)
#   - Android SDK Platform-Tools
#   - NDK (Side by side)
#   - Android SDK Command-line Tools

# 環境変数
export ANDROID_HOME="$HOME/Library/Android/sdk"
export NDK_HOME="$ANDROID_HOME/ndk/<version>"
export PATH="$PATH:$ANDROID_HOME/platform-tools"

# Rust target
rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android

# Tauri Android プロジェクト生成
pnpm tauri android init

pnpm tauri android dev                       # エミュレータ / 実機で起動

現在の進捗 (2026-06 時点)

✅ Phase 1 完了

カテゴリ 状態
UI / 体験 (対面挨拶 / 広場 / プロフィール / ウォークモード) 全機能実装済み
Supabase 連携 (匿名 Auth / RLS / 同意 / 一括 fetch / バックオフ + トースト) 実装済み
ローカル DB (SQLite + migration 0001 / 0002) 実装済み
実 BLE Scan (btleplug @ desktop) 実装済み
iOS プロジェクト + Bluetooth 権限 + 縦固定 生成済み
Android Manifest / BLE permission plugin 側に実装済み

✅ Phase 1.5: iOS / Android Native BLE プラグイン

btleplug は iOS/Android 非対応のため、Mobile では tauri-plugin-encounter-ble を使う。Android は Service Data + GATT characteristic、iOS は CoreBluetooth の 制約に合わせて Service UUID advertise + GATT read fallback で user_id を交換する。

実装済み:

  • src-tauri/plugins/tauri-plugin-encounter-ble に iOS Swift / Android Kotlin plugin を追加
  • BleBackend::TauriPlugin を追加し、mobile では未指定時に自動採用
  • native plugin event を既存の encounter 保存フローへ接続
  • Android debug APK build は通過済み
  • iOS simulator bundle / iPhoneOS .ipa build は通過済み

残課題:

  • 実機 (iPhone × 2, Android × 1 程度) で相互検出テスト
  • iOS 実機インストールには Apple Developer Team / signing 設定が必要

詳細は docs/specs/ble-handshake.md §7 を参照。 実機検証手順は docs/specs/ble-real-device-test.md を参照。

Phase 2 (要件定義 §7)

  • アバター完全 3D 化 (R3F + glTF)
  • LLM ベースの会話生成
  • 表情軸 / アクセサリ軸の拡張

Phase 3 (要件定義 §7)

  • AVATAVI STORE プラットフォーム
  • Go 自前バックエンド (Supabase 置換)
  • 着せ替え販売

開発時 Tips

dev preview ページ (Tauri 不要、ブラウザで動作)

URL 用途
/encounter-preview 対面挨拶シーンを iPhone 13 サイズ枠で確認
/plaza-preview 広場ビューを 0/1/8/32/60 人で確認、合流アニメ再生
/avatar-preview アバターパーツの組み合わせ確認

process.env.NEXT_PUBLIC_ENABLE_DEV_PAGES=0 で本番無効化。

バックエンド切り替え

# BLE 実装
BLE_BACKEND=mock pnpm tauri:dev      # mock peer ループ強制
BLE_BACKEND=btleplug pnpm tauri:dev  # btleplug (macOS) 強制
BLE_BACKEND=tauri-plugin pnpm tauri:dev  # mobile native plugin 強制
# 未指定は desktop なら btleplug、iOS/Android は tauri-plugin

# Supabase mock モード
# .env.local の URL/ANON_KEY を空にすると Rust の profile_fetch_remote にフォールバック

既知の落とし穴

  • output: 'export' の Next.js: pnpm build 後は .next / out を削除しないと pnpm dev がキャッシュ衝突する
  • tauri-plugin-sql の permission: capabilities/default.jsonsql:allow-load / sql:allow-execute / sql:allow-select / sql:allow-close を明示
  • Tauri エラーは string: error instanceof Error が false になるので asError(e) でラップ
  • dev server ポート 1420 固定: package.jsondev: next dev -p 1420tauri.conf.jsondevUrl を一致
  • SSR で Math.random() / Date.now() 禁止: hydration mismatch を起こす。useEffect 内で生成して setState する (例: SakuraPetals)

About

BLE proximity avatar app (spec-driven, Tauri v2 + Next.js)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors