Skip to Content
Apps & PortalsMobileMobile App — Dashboard (Tenant)

Mobile App — Dashboard (Tenant)

The Dashboard app ships on two platforms from a single codebase: web (Next.js) and mobile (React Native). The mobile app targets tenant users (clients) who need to review, approve, and manage their marketing pipeline on the go.

Audience: Dashboard/client users only. For the DM reviewer mobile app, see dm-mobile.md.


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
Push notificationsExpo Notifications (FCM + APNs) — Phase 4
AuthJWT (access + refresh tokens) stored in SecureStore
Real-timeSSE via react-native-sse
Offline cachereact-native-mmkv + TanStack Query persist

Monorepo placement

apps/ dashboard/ # Next.js web app dashboard-mobile/ # React Native app (Expo bare) — this app dm-mobile/ # React Native app for DM reviewers (see dm-mobile.md)

Shared code (between web and mobile):

  • packages/common — format utilities, badge colours

Not shared — diverges per platform:

  • UI components (web: shadcn/ui + Tailwind; mobile: React Native StyleSheet)
  • Navigation (web: Next.js App Router; mobile: React Navigation)
  • Data fetching (web: Server Actions; mobile: /mobile/v1 Fastify endpoints)

Feature Parity

The mobile app exposes the same user actions as the web dashboard. No features are downgraded to view-only unless noted.

FeatureMobile behaviour
Approve context / strategy / planFull approve flow with confirmation
Request revisionBottom sheet with free-text notes → AI regenerates
Strategy status changeFull status picker: Draft / Pending Review / Approved / Rejected
View timelineContent | Timeline | Details tab strip on all 3 pipeline screens
Strategy version historyVersion picker pill in header
Edit contentNot on mobile — revision request covers the use case
DM plan editing (goals/templates)Not on mobile — DM portal is web-only

Screen Availability

ScreenWeb dashboard IDMobileNotes
HomeD1✅ MVPSimplified stat cards; deep-link into other screens
Marketing StrategyD2✅ MVPContent | Timeline | Details tabs; full status picker; revision request
GoalsD3✅ MVPProgress bars, monthly targets; read-only
LeadsD4✅ MVPView + status changes
DeliverablesD5✅ MVPRead-only; period picker + expandable rows
ActivitiesD6✅ MVPList view only (no calendar/kanban/grouped)
Activity DetailD6 detail✅ MVPRead-only output view
ChannelsD7✅ MVPView status; connect via system browser
ReportsD8🔜 Phase 2Monthly performance snapshot
Report DetailD9🔜 Phase 2Full report document
Business Info / VaultD10🔜 Phase 2Subscriptions, invoices, email preferences
UsersD11Management task; not on mobile
Agent ChatD12✅ MVPAI assistant; streaming responses via SSE
Client ContextD12a✅ MVPContent | Timeline | Details; approve + revision request
Profile / SettingsD13✅ MVPName, email, theme switcher (light/dark/system), sign out
Agent DetailD14Too detailed for mobile
Social PostsD15✅ MVPStatus tabs; approve/reject
Social Post DetailD15b✅ MVPFull preview + approve/reject with notes
Approvals Queue✅ MVPAll pending approvals (blog, generic content)
Approval Review✅ MVPScrollable Markdown + pinned action bar
Deliverable Plan✅ MVPContent | Timeline | Details; status-aware action bar; 4-status flow
Notifications✅ MVPBell icon; full history; mark-as-read
Blog Requests✅ MVPView + approve
Social Requests✅ MVPView + approve

Deliverable Plan — 4-status flow

The plan goes through two approval stages before execution begins:

pending_review → DM (web portal) reviews and edits goals/templates dm_approved → Client can see the plan and approve it (mobile or web dashboard) approved → Plan locked; Activity Planner enqueued; execution begins archived → Superseded plan (read-only history)

Mobile behaviour per status:

StatusMobile shows
pending_review”Your account manager is reviewing the plan” — auto-refresh every 15s
dm_approvedFull goals + templates + Approve Plan button
approvedRead-only + “Approved” badge + Timeline tab

Header (persistent across all tabs) └── 🔔 Bell icon → Notifications screen (full history + mark-as-read) Bottom Tab Bar ├── 🏠 Home (D1 — Home) │ Stat cards deep-link into other screens ├── ✅ Approvals (Approvals Queue — blog + generic content) │ └── /[id] (Approval Review) ├── 📋 Activities (D6 — Activities list) │ └── /[id] (Activity Detail — read-only output) ├── 💬 Chat (D12 — Agent Chat with SSE streaming) └── ⚙️ More ├── Client Context (D12a — Content|Timeline|Details tabs + approve + revision) ├── Strategy (D2 — Content|Timeline|Details + status picker + versions) ├── Deliverable Plan (Goals + Templates + Timeline; 4-status aware) ├── Social Posts (D15 list → D15b detail — separate from Approvals tab) ├── Blog Requests (view + approve) ├── Social Requests (view + approve) ├── Leads (D4 — view + status changes) ├── Channels (D7 — view + connect via system browser) └── Profile (theme switcher, account info, sign out)

API Layer

The mobile app calls a dedicated /mobile/v1 Fastify router. All routes require a valid tenant JWT.

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

Endpoints

MethodPathDescription
GET/homeDashboard stats (stage, goals, activities, approvals)
GET/activitiesPaginated activity list
GET/activities/:idActivity detail + output
GET/approvalsPending approvals queue
GET/approvals/:idSingle approval item by ID
POST/approvals/:id/resolveApprove or reject an approval
GET/contextClient context (status, content, version)
POST/context/approveApprove context → triggers strategy writer
POST/context/revisionRequest revision with notes → AI regenerates
GET/context/logsContext activity timeline
GET/strategyStrategy (status, content, version)
PATCH/strategy/statusUpdate strategy status
POST/strategy/revisionRequest revision → AI regenerates
GET/strategy/logsStrategy activity timeline
GET/strategy/versionsAll strategy versions
GET/deliverablesDeliverable plan + goals + templates + active period
POST/deliverables/approveApprove plan → enqueues activity planner
GET/deliverables/logsDeliverable plan activity timeline
GET/goalsActive goals list
GET/social-postsSocial posts list
GET/leadsLeads list
PATCH/leads/:id/statusUpdate lead status
GET/channelsConnected channels
GET/blog-requestsBlog posts awaiting client review
GET/social-requestsSocial posts awaiting client review
GET/notificationsNotification history
PATCH/notifications/readMark all notifications as read

Push Notifications

EventNotificationDeep link target
New approval pending (high risk)”🔴 High-risk content needs your review”Approval Review
New approval pending (normal)”📝 Content ready to review”Approval Review
Agent completed a task”✅ SEO Specialist completed keyword research”Activity Detail
Agent error / escalation”⚠️ Agent hit an error — tap to review”Activity Detail
New social post ready”📱 Social post ready for approval”Social Post Detail
Deliverable plan ready”📋 Your plan is ready to review”Deliverable Plan

Implementation:

  • @react-native-firebase/messaging on the client (not Expo Push) — direct FCM via google-services.json
  • Firebase Admin SDK (@leadmetrics/provider-firebase) on the server — uses Application Default Credentials
  • FCM token stored in push_device_token table (unique per token, with userId + tenantId)
  • registerForPushNotifications() called after login; unregisterPushNotifications() called before logout
  • Email co-dispatch: every email sent by apps/servers/notifications also fires push to the same recipients (best-effort, non-blocking)
  • Admin broadcast: POST /admin/v1/push/broadcast — superadmin only, sends to all registered tokens
  • Tenant notify: POST /admin/v1/push/tenants/:tenantId/notify — sends to all members of a tenant
  • Stale token pruning: tokens that fail FCM delivery are automatically deleted from the DB

Required setup:

  1. Firebase project → download google-services.json → place at android/app/google-services.json
  2. Run gcloud auth application-default login as the Firebase project owner for ADC
  3. Set GOOGLE_CLOUD_PROJECT=<firebase-project-id> in apps/api/.env and apps/servers/notifications/.env — the project ID must match the project_id in google-services.json

Mobile-Specific UX Notes

Action bar pattern

Status-aware action bar pinned to bottom of pipeline screens (Context, Strategy, Deliverable Plan):

  • pending_review → Approve + Request Revision buttons
  • generating → Loading indicator “AI is working…”
  • approved → Read-only badge

Revision request

Bottom sheet slides up with a text input for notes. Submitting triggers AI regeneration with the feedback as context.

Strategy version picker

Version pill button in the header (e.g. “v3 ▾”) opens a modal list of all past versions. Tapping a version loads its content.

Tab strip (Content | Timeline | Details)

All three pipeline screens (Context, Strategy, Deliverable Plan) use a 3-tab layout:

  • Content — full markdown view of the document
  • Timeline — chronological activity log (generated, approved, revised, status changes)
  • Details — metadata (status, version, dates, cost estimate)

OAuth channel connect

“Connect Channel” opens the system browser — not an in-app WebView — to comply with OAuth provider restrictions (Google, LinkedIn).

Offline behaviour

TanStack Query caches last-fetched data for offline viewing. Approval submissions are queued locally and retried on reconnect.


Auth Flow

  1. First launch: email + password login (same credentials as web)
  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 — queued requests resume with new token

Development

cd apps/dashboard-mobile pnpm start # Expo Metro dev server pnpm android # Android Emulator (requires Android SDK) pnpm ios # iOS Simulator (requires Xcode, macOS only)

© 2026 Leadmetrics — Internal use only