Skip to Content
Apps & PortalsMobileMobile App — DM Portal (Reviewer)

Mobile App — DM Portal (Reviewer)

The DM mobile app is a React Native companion to the web-based DM Portal (apps/dm). It lets DM reviewers manage cross-tenant content approvals, review client context and strategy, and monitor agent activity from their phone.

Audience: DM reviewers and account managers only. Tenant users use dashboard-mobile.


Technology

LayerTechnology
FrameworkExpo bare workflow + React Native 0.83
NavigationReact Navigation v7 (bottom tabs + native stack)
State / data fetchingTanStack Query v5
Token storageexpo-secure-store (iOS Keychain / Android Keystore)
Biometricsexpo-local-authentication
Offline cachereact-native-mmkv + TanStack Query persist
AuthJWT (access + refresh tokens) stored in SecureStore

Monorepo placement

apps/ dm/ # Next.js web DM portal dm-mobile/ # React Native app (Expo bare) — this app

Shared code:

  • packages/common — format utilities, badge colours

API prefix: All endpoints are under /dm/v1 on the Fastify API.


Bottom Tab Bar ├── 🏠 Overview — Cross-tenant stats + pending approvals + running agents ├── 📝 Content Hub — Tabbed list: Blog | Social posts (across all tenants) └── ⚙️ More ├── Client Context — Context review + revision request (per tenant) ├── Strategy — Strategy review with version history (per tenant) ├── Deliverables — Deliverable progress view (per tenant) └── Profile — Account info, theme switcher, sign out

All screens requiring a specific tenant prompt the user to select from their assigned tenants via TenantContext.


Screen Coverage

ScreenStatusNotes
Login✅ MVPEmail + password; app: "dm" login type
Overview✅ MVPStats (pending approvals, running agents, escalations, active tenants); filterable approval queue
Content Hub✅ MVPTabbed blog + social lists across all tenants; approve / reject / request revision
Blog Detail✅ MVPFull content view; DM approve / reject with optional feedback
Social Detail✅ MVPPlatform preview; DM approve with channel + schedule picker; reject with feedback
Client Context✅ MVPScrollable Markdown; request revision with notes
Strategy✅ MVPScrollable Markdown; version history list
Deliverables✅ MVPPeriod picker; template rows with completion %
Profile✅ MVPName, email, theme (light/dark/system), sign out

API Layer

Base URL: http(s)://<api-host>/dm/v1

All routes require a valid DM JWT (Authorization: Bearer <token>).

MethodPathDescription
GET/overview-statsCross-tenant stats: pending approvals, running agents, escalations, active tenants
GET/overview-approvalsPaginated pending approval queue (filterable by type and platform)
GET/overview-runningCurrently running agent jobs
GET/context?tenantId=Client context content + logs for a tenant
POST/context/revise?tenantId=Request context revision with notes
GET/strategy?tenantId=Strategy content + version history + logs for a tenant
GET/blog?tenantId=Paginated blog post list (filterable by status)
GET/blog/:idBlog post detail
POST/blog/:id/dm-approveDM approve a blog post
POST/blog/:id/dm-rejectDM reject a blog post with optional feedback
GET/social?tenantId=Paginated social post list (filterable by platform and status)
GET/social/:idSocial post detail
GET/social/:id/channelsAvailable channels for scheduling
POST/social/:id/dm-approveDM approve + assign channel + optional scheduledAt
POST/social/:id/dm-rejectDM reject with optional feedback
GET/deliverables?tenantId=Deliverable templates + progress + period options for a tenant

Auth endpoints shared with all apps:

MethodPathDescription
POST/auth/v1/loginLogin with app: "dm"
GET/auth/v1/meCurrent user profile
GET/auth/v1/me/tenantsTenants accessible to the logged-in DM
POST/auth/v1/refreshRefresh access token

Auth Flow

  1. First launch: email + password login (same DM credentials as the web portal)
  2. On success: biometric (Face ID / fingerprint) prompt to enable quick unlock
  3. Subsequent opens: biometric unlock (no password re-entry)
  4. Token storage: expo-secure-store (iOS Keychain / Android Keystore)
  5. Token refresh: automatic on 401 — in-flight requests resume with the new token
  6. Login specifies app: "dm" — only accounts with DM/reviewer access are accepted

Tenant Selection

DMs work across multiple tenants. TenantContext holds the currently selected tenant. Screens that require a tenant (Context, Strategy, Deliverables, Blog, Social) read from this context and let the user switch tenants without logging out.


Development

# From the monorepo root pnpm --filter @leadmetrics/dm-mobile dev # Or from apps/dm-mobile npx expo start # Metro dev server npx expo run:android # Build + install on Android emulator (requires Android SDK) npx expo run:ios # Build + install on iOS Simulator (requires Xcode, macOS only)

Windows / pnpm notes

Building on Windows with pnpm requires short-path workarounds due to the 260-character MAX_PATH limit. See the init script at ~/.gradle/init.d/cmake-short-path.gradle for the Gradle + CMake redirects that make the Android build work on Windows. The script redirects buildDir for pnpm-store modules to E:/lm-build/<module> and CMake staging to C:/lm-cmake/<module>.

Metro config (metro.config.js) excludes Next.js .next/ build directories from file watching to prevent ENOENT crashes when sibling web apps run simultaneously.

Environment

VariableDescription
EXPO_PUBLIC_API_URLFastify API base URL (default: http://localhost:3003)

Copy .env.example to .env and set EXPO_PUBLIC_API_URL for non-local environments.

© 2026 Leadmetrics — Internal use only