Appearance
hi-yu(ふたりの気配コンパス)
ペアになった 2 人が、相手の正確な場所ではなく 方向と大まかな距離感だけを感じるアプリ。 「地図ではなく光、距離ではなく雰囲気、監視ではなく気配」がコンセプト。
- リポジトリ:
~/Documents/project/hi-yu(GitHub: y0r4/hi-yu・private) - 設計:
docs/hi-yu 詳細設計書 v1.md/実装現状:docs/実装状況.md - CI:GitHub Actions(push で
swift run hiyu-checkを自動実行)
技術スタック
| 領域 | 採用 |
|---|---|
| アプリ | SwiftUI(iOS 17+、Xcode 26.5) |
| 構成 | HiYuCore(SPM・純ロジック)+ app(XcodeGen 生成) |
| バックエンド | CloudKit + APNs(実装済み・実機 2 台で検証済み。Production スキーマ Deploy 済み) |
| 署名 | Developer Program(当初は無料 Personal Team、Bundle ID hiyu.yur4.net) |
| ロジック検証 | HiYuCore は実行ターゲット(swift run hiyu-check)+ assert でテスト 70 項目合格 |
主要な設計判断
- SwiftUI + CloudKit(Flutter+Firebase から変更)。iOS 先行。 CloudKit はサーバーレス・無料・iCloud=ID で機種変更でもペア維持・審査が楽。 代償は Android ロックイン(MVP は検証目的で許容)。
- 位置プライバシー:生座標を共有し各端末で方向・距離を計算(クライアント計算)。
- 近接通知も端末側判定(サーバーレス)。
- 表示ロジックは HiYuCore に純関数化してテスト(StarPresentation=近さ/サイズ/位置/ぼかし、 Geo、Pairing、Battery、Invite)。SwiftUI 非依存で CI 検証。View は呼ぶだけ。
- 外部依存はプロトコルで抽象化:相手状態=
PartnerStore(+Mock/CloudKit骨格)、 招待=InviteBackend(+Mock/CloudKit骨格)。CloudKit 加入後はバックエンド差し替えで接続。 - 相手の星のぼかしは「相手が最後にアプリを開いてからの時間(partnerIdle)」で判定(位置の 更新時刻でも自分の起動時刻でもない)。12h まではくっきり→3日で最大ぼかし→7日で非表示。 表示中に相手が開いたら 10 秒かけて徐々にくっきり。CloudKit の相手 lastOpened が実データ源。 ※旧 FreshnessStage(fresh/stale/old) は app では不使用・Core に残置(近接通知用)。
- 演出方針:不規則な揺れやコンパス精度ぼかしは世界観(星空・気配)に合わないため不採用。
体験・演出(実装済み)
- 星空テーマ:自分=中央の星(一番近いときの相手と同じ大きさ)、相手=方向の星。 サイズ・中央への寄り・空の色は距離に応じて段階なく連続変化(近さは 20m=最大〜20km=最小の log スケール、空は 5 バンド色を補間)。背景星空、呼吸する halo。相手の写真を星に使える。
- ふりふり:ハートのバースト(全画面・約 6 秒)→ 相手方向へハートが飛ぶ(送信は正面±35°時のみ、 受信は逆順)。
- チュートリアル(初回+ヘルプ・日英)、オンボーディング(招待QR表示+QR読取カメラ/リンク貼付/同意/権限)、 設定(通知・電池 3 段階、解除ゲージ、言語、写真)。
- 近接ローカル通知(前面・外→内+クールダウン)、電池モード→位置精度の反映、位置オフ/向き未取得の案内UI。
- デモパネルは
#if DEBUG限定(リリースに出ない)。主要画面に SwiftUI #Preview。
加入待ちに進めた先行作業(このセッション)
- 表示ロジックの Core 抽出+テスト 70 項目化、CI/README 追加。
- PartnerStore/PairingService 抽象化と CloudKit/CKShare スケルトン(fetch/report/招待は no-op、 CKRecord↔Snapshot・CKShare 受理の足場とTODO)。
- LocationService の Always 要求・significant location change、NotificationService、 自分の lastOpened 記録、QRScannerView(AVFoundation)。配線とテストは完了、実データ接続が残り。
リリース準備状況(2026-07-02 時点)
v1.0 の App Store リリース準備中。docs/リリース指示書.md(Phase 0〜7、担当 agent/人間・ 完了条件・既知のハマり付き)が再開ポイントの正。
完了済み:
- Mock ブロッカー解消:
useCloudKitSync既定 false=Mock のままだと本番が Mock(東京駅固定)で 動く状態だった →isCloudKitEnabled()(MainView.swift)に判定集約、Release は常に CloudKit。 - CloudKit Production スキーマ Deploy 済み(planet/unpaired/message/MoonGift)。
- Archive→Export パイプライン検証済み: IPA に PrivacyInfo/NSE 同梱・
aps-environment=production確認。 ハマりどころは [[ios-appstore-release-checklist]] に集約。 - ストア文書起草:
docs/store/プライバシーポリシー.md(日英)、docs/store/ASCメタデータ.md(説明文・キーワード・App Privacy 回答案・審査メモ英文・スクショ計画)。 - 投げ銭 IAP(B2)は実装済み(
net.yur4.hiyu.tip.small/medium/largeの 3 種)。
残作業(すべて人間の操作待ち):実機 2 台×別 iCloud での検証(再ペア・解除検知・背景位置/近接)、 ASC 登録(Paid Apps 契約・App レコード・IAP 3 種+Sandbox 購入検証)、プライバシーポリシーの ホスト先 URL、スクショ採取・デモ動画(審査対策・必須級)、検証完了後の提出用 Archive→アップロード。
関連
- 無料アカウントでの iOS 実機ビルド手順 → [[ios-free-team-device-build]]
- リリース実務のハマりどころ → [[ios-appstore-release-checklist]]
- CloudKit サーバレス Push 設計 → [[cloudkit-serverless-push-delivery]]