Skip to content

Mobile App

The Klaxon mobile app is built with Expo (React Native) and supports iOS and Android.

Features

  • Item list with pull-to-refresh, level badges, and cursor pagination
  • Full-text search with debounced input
  • Channel filtering — tap a channel to filter the items list
  • Item detail with action buttons (ack, dismiss, archive)
  • Form answering with 15 field types (draft persistence across app backgrounds)
  • Snooze picker (1h, 4h, Tomorrow)
  • Comments (view thread + add)
  • FCM push notifications with deep linking to item detail
  • Settings: server URL, login/logout, quiet hours (start/end/allow levels)

Running Locally

bash
cd apps/klaxon-mobile
npx expo start

Scan the QR code with Expo Go, or press i for iOS simulator / a for Android emulator.

Stack

LibraryPurpose
Expo SDK 54Framework
Expo Router 6File-based navigation
TanStack Query 5Server state + caching
expo-secure-storeToken persistence
@react-native-firebase/messagingFCM push notifications
@ottercoders/klaxon-protocolShared Zod types

Authentication

The app stores the bearer token in expo-secure-store (encrypted device storage). The Settings tab provides server URL configuration and email + org login.

Magic link login: the mobile app requests a magic link, user receives email, taps the link which opens the app and creates a session.

Push Notifications (FCM)

Firebase Cloud Messaging handles both Android and iOS (FCM routes to APNs):

  1. App requests notification permission on login
  2. FCM device token registered with server (POST /api/push/register)
  3. Token refresh handled automatically
  4. Tap notification → deep link to /item/:id

Requires google-services.json (Android) and GoogleService-Info.plist (iOS) from Firebase console. Configure via EAS Build secrets for production.

Deep Linking

The app registers the klaxon:// URL scheme. Push notifications deep-link to item detail:

klaxon://item/<uuid>

The Items tab has a search input at the top. Search is debounced (300ms) and uses the server's full-text search (?q= parameter with PostgreSQL plainto_tsquery).

Channel Filtering

Tap a channel in the Channels tab to filter the Items list. A "Filtered by #channel" chip appears with a clear button.

Form Field Types

15 of 22 field types are supported on mobile. Deferred to v2:

  • fileupload (needs native camera/gallery/file pickers)
  • diffapproval (needs syntax-highlighted diff renderer)
  • markdown (needs React Native markdown renderer)

Form drafts are persisted to localStorage — users don't lose progress if the app backgrounds.

Quiet Hours

Settings tab includes notification controls:

  • Toggle quiet hours on/off
  • Start/end time (HH:MM format)
  • Allow levels during quiet hours (comma-separated, e.g. "error,warning")

Settings sync to the server via PUT /api/settings/:key.