soconnor 3daf123399 Add App Store Connect submission guide with copy and privacy answers.
Document metadata, descriptions, review notes, demo credentials, and pre-submission checklist for the iOS release.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-18 01:34:44 -04:00
2026-06-17 15:44:12 -04:00
2026-06-17 15:44:12 -04:00
2026-06-17 15:44:12 -04:00
2026-06-17 15:44:12 -04:00

beenvoice Mobile

Expo companion for beenvoice — dashboard, time clock, invoices, clients, businesses, and settings. Shares the same tRPC API and better-auth sessions as the web app.

Architecture (dense): docs/ARCHITECTURE.md

Prerequisites

  • Bun 1.3+
  • beenvoice API running (setup)
  • Xcode + iOS Simulator (or device) for native dev build
  • Not Expo Go — widgets, SecureStore auth, and biometrics need expo-dev-client

Setup

cd beenvoice-app
bun install
cp .env.example .env

.env:

# Simulator
EXPO_PUBLIC_API_URL=http://localhost:3000

# Physical iPhone — Mac LAN IP
EXPO_PUBLIC_API_URL=http://192.168.1.42:3000

Omit EXPO_PUBLIC_API_URL in production builds to default to https://beenvoice.soconnor.dev.

Server must enable @better-auth/expo in beenvoice/src/lib/auth.ts with beenvoice:// in trustedOrigins.

Run

# Terminal 1 — API
cd ../beenvoice && bun run dev

# Terminal 2 — mobile (builds native app if needed)
cd beenvoice-app && bun run ios

Metro uses port 8082 (avoids other Expo projects on 8081).

Metro only (app already installed):

bun run start -- --clear

Open the beenvoice dev build on the simulator — not Expo Go.

After native changes

Icon (assets/beenvoice.icon), widgets, or new native modules:

bunx expo prebuild --platform ios --clean
bun run ios

Features

Area Details
Auth Sign in, register, forgot/reset password; official or self-hosted server
Multi-account Bitwarden-style switcher; per-account session in SecureStore
Dashboard Revenue, pending, overdue, running timer, recent invoices
Timer Clock in/out, client + invoice + rate; optional description (default "Clock In"); iOS Live Activity
Entities Clients and businesses — list, create, edit
Invoices List, filter, create, edit, status updates
Settings Profile, accounts, theme, per-account app lock (PIN + Face ID), sign out
App lock Per-account; locks on background return

Auth & accounts (summary)

  • Guest auth storage: beenvoice:guest until first successful login
  • Per account: beenvoice:auth:{host::userId} in SecureStore
  • After login, finalizeAuthenticatedAccount() migrates session keys before activating the account (avoids double login)
  • Server picker: Official (beenvoice.soconnor.dev) or custom URL on auth screens

Full flow: docs/ARCHITECTURE.md#multi-account-model

Scheme Screen
beenvoice://reset-password?token=… Reset password
beenvoice://timer Timer tab (from Live Activity)

Project layout

app/
  _layout.tsx           # Providers, auth guard
  (auth)/               # sign-in, register, password flows
  (app)/                # tab shell + nested stacks
components/             # UI, forms, chrome, time clock
contexts/               # Auth, Accounts, AppLock, Theme
lib/                    # tRPC, auth storage, config, theming
widgets/                # iOS Live Activity (TimeClockActivity)

Troubleshooting

Issue Fix
PlatformConstants / runtime not ready Stop other Metro on 8081/8082; rebuild with prebuild --clean
Expo Go Use bun run ios dev build
API errors on device EXPO_PUBLIC_API_URL = Mac LAN IP; server BETTER_AUTH_URL must match
Live Activity empty Rebuild iOS; widget UI must live inside "widget" function
Login twice Server + app versions with session migration (lib/auth-storage.ts)
S
Description
beenvoice mobile app (Expo/React Native)
Readme 1.2 MiB
Languages
TypeScript 94.6%
Shell 2.9%
JavaScript 1.6%
Swift 0.9%