Skip to main content

Mobile & Native Development

Framework M is designed as a 90% Mobile-Ready foundation. Because we utilize Tamagui for our design system and core layout components, your UI code is cross-platform by default.

This guide outlines how to bridge the remaining 10% of architectural logic to target React Native (iOS, Android) and Desktop (macOS, Windows).

Foundational 90% (Tamagui)

Our @framework-m/ui and @framework-m/desk libraries use Tamagui's Stacks and Themes. Tamagui's compiler automatically:

  • Compiles to optimized atomic CSS for the Web.
  • Compiles to standard React Native View/Text for mobile.

[!TIP] Always prefer Tamagui tokens (e.g., backgroundColor="$background") over raw CSS variables to ensure platform compatibility.

Getting Started with Native

Framework M libraries are published on NPM and PyPI. You can install them into any standard React Native or Expo project just like any other package.

pnpm add @framework-m/ui @framework-m/desk @framework-m/plugin-sdk

The Remaining 10%: Architectural Gaps

While 90% of your code (UI, business logic, and plugins) is cross-platform, you must address four specific architectural translations to bridge between Web and Native.

1. Unified Routing

The web-first shell uses react-router-dom. For Native, we recommend React Navigation for its high-performance flexibility in dynamic composition.

  • Bridging Strategy: Use the @framework-m/plugin-sdk to iterate over discovered plugins and dynamically generate a Stack or Tab navigator.
  • Expo Router Alternative: If you prefer file-based routing and web-parity, Expo Router is a high-quality alternative.

2. Unified Authentication & Tokens

Framework M utilizes a Unified Authentication Chain that allows a single backend to fulfillment of both Web and Native clients simultaneously. This the configured via the auth.strategies list in your framework_config.toml.

How Parallel Auth Works:

  1. Web (Session Strategy): The backend issues an HttpOnly session cookie—secure for browsers but difficult for native apps.
  2. Native (JWT / OIDC Strategy): The backend accepts an Authorization: Bearer <token> header.
    • In Indie Mode (jwt strategy): The backend issues its own internal JWT signed with a private Local JWT Secret. The Native app only holds the token; the secret must never be included in the app bundle.
    • In Federated Mode (oidc strategy): The backend directly accepts and validates an external OIDC token (e.g., Google, Azure AD, Auth0) using the configured [auth.oauth] providers, automatically fetching JWKS and caching public keys.
    • Behind an API Gateway (gateway strategy): The backend trusts hydrated HTTP headers (e.g., X-User-ID) injected by an upstream proxy that has already authenticated the native token.

[!CAUTION] Client Security: Your backend JWT_SECRET or OIDC CLIENT_SECRET are private keys. Including them in a React Native or Desktop binary is a critical security failure. The client should only ever hold short-lived Tokens and long-lived Refresh Tokens in secure storage.

The Native Refresh Lifecycle:

  • Client Ownership: The Native app is responsible for the refresh lifecycle. It must store the Refresh Token in secure storage (Keychain/Keystore).
  • Graceful Refresh: Use a high-quality interceptor to catch 401 Unauthorized responses and negotiate a new Access Token before retrying the request.

3. Unified Storage

While the web shell uses localStorage, Native platforms require securely encrypted storage for tokens.

Implementation Recommendation:

// libs/framework-m-ui/src/storage.ts
import { Platform } from 'react-native';

// Standard native keychain wrapper
export const secureStorage = Platform.OS === 'web'
? null // Web should use HttpOnly Cookies, not local tokens
: require('react-native-keychain');

4. Unified API Bridge

Features like Camera, Biometrics, and Push Notifications require platform-specific permissions and APIs.

  • Use Expo SDK for a high-quality set of universal APIs.
  • Utilize the Slot system in @framework-m/desk to provide Native-only entry points without affecting the web layout.