Files
beenvoice-app/README.md
T
soconnor 32ffe782ea Fix Live Activity lock screen rendering and polish multi-account auth.
Flatten widget layouts and use system colors so banner and expanded regions render on vibrant lock screens; migrate auth sessions per account to prevent double sign-in; scope app lock PIN to accounts; default clock description to "Clock In"; add architecture docs and deferred form validation on auth screens.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-18 01:23:36 -04:00

3.8 KiB

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)