@molecule/app-react-native

Framework · framework · App (browser) · v1.0.2 · Apache-2.0

React Native framework bindings for molecule.dev

npm install @molecule/app-react-native

npm · Source on GitHub

How it works

@molecule/app-react-native adapts the @molecule/* cores to the framework framework on the app (browser) side.

import { MoleculeProvider, useAuth, useAppState, useSafeArea } from '@molecule/app-react-native'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import { View } from 'react-native'
import { provider as stateProvider } from '@molecule/app-state-zustand'
import { createJWTAuthClient } from '@molecule/app-auth'

const authClient = createJWTAuthClient({ baseURL: 'https://api.example.com' })

function Shell() {
  const { isAuthenticated } = useAuth()
  const { isActive } = useAppState()
  const insets = useSafeArea()
  return (
    <View style={{ paddingTop: insets.top }}>{isAuthenticated && isActive ? <View /> : null}</View>
  )
}

function App() {
  return (
    <SafeAreaProvider>
      <MoleculeProvider state={stateProvider} auth={authClient}>
        <Shell />
      </MoleculeProvider>
    </SafeAreaProvider>
  )
}

Reference

React Native framework bindings for molecule.dev.

Re-exports every hook and provider from @molecule/app-react (they are pure React — no DOM dependency) and adds RN-specific hooks: useAppState (foreground/background), useBackHandler (Android back button), useKeyboardHeight, and useSafeArea.

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

Quick Start

import { MoleculeProvider, useAuth, useAppState, useSafeArea } from '@molecule/app-react-native'
import { SafeAreaProvider } from 'react-native-safe-area-context'
import { View } from 'react-native'
import { provider as stateProvider } from '@molecule/app-state-zustand'
import { createJWTAuthClient } from '@molecule/app-auth'

const authClient = createJWTAuthClient({ baseURL: 'https://api.example.com' })

function Shell() {
  const { isAuthenticated } = useAuth()
  const { isActive } = useAppState()
  const insets = useSafeArea()
  return (
    <View style={{ paddingTop: insets.top }}>{isAuthenticated && isActive ? <View /> : null}</View>
  )
}

function App() {
  return (
    <SafeAreaProvider>
      <MoleculeProvider state={stateProvider} auth={authClient}>
        <Shell />
      </MoleculeProvider>
    </SafeAreaProvider>
  )
}

Type

framework

Installation

npm install @molecule/app-react-native @molecule/app-keyboard @molecule/app-lifecycle @molecule/app-react react react-native react-native-safe-area-context

API

Interfaces

AuthState

Reactive authentication state snapshot (initialized, authenticated, user, loading, and error).

interface AuthState<T = UserProfile> {
  /**
   * Whether auth state has been initialized.
   */
  initialized: boolean
  /**
   * Whether the user is authenticated.
   */
  authenticated: boolean
  /**
   * Current user (if authenticated).
   */
  user: T | null
  /**
   * Whether an auth operation is in progress.
   */
  loading: boolean
  /**
   * Last auth error (if any).
   */
  error: string | null
}

AuthClient

Auth client interface that all auth bond packages must implement. Provides login/logout/register flows, token management, profile updates, and auth state subscription.

interface AuthClient<T = UserProfile> {
  /**
   * Returns the current authentication state snapshot.
   */
  getState(): AuthState<T>
  /**
   * Returns whether the user is currently authenticated.
   */
  isAuthenticated(): boolean
  /**
   * Gets the current user.
   */
  getUser(): T | null
  /**
   * Updates the cached user object (state + persistent storage) without
   * hitting the network. Intended for local refreshes after a per-app
   * mutation (e.g., the user just PATCHed their own profile and the
   * server returned the canonical row). Does NOT change tokens.
   */
  setUser(user: T | null): void
  /**
   * Gets the current access token.
   */
  getAccessToken(): string | null
  /**
   * Stores the access token in the configured token storage adapter (in-memory
   * by default). Use this to seed the token after an out-of-band exchange (e.g.
   * the OAuth code→token redirect) instead of writing to `localStorage` directly,
   * which would violate the in-memory-default storage contract and make the bearer
   * token JS-readable (XSS-exfiltratable). Pass `null` to clear it.
   */
  setAccessToken(token: string | null): void
  /**
   * Gets the refresh token.
   */
  getRefreshToken(): string | null
  /**
   * Logs in with credentials.
   */
  login(credentials: LoginCredentials): Promise<AuthResult<T>>
  /**
   * Logs out the current user.
   */
  logout(): Promise<void>
  /**
   * Registers a new user.
   */
  register(data: RegisterData): Promise<AuthResult<T>>
  /**
   * Refreshes the access token.
   */
  refresh(): Promise<AuthResult<T>>
  /**
   * Requests a password reset.
   */
  requestPasswordReset(data: PasswordResetRequest): Promise<void>
  /**
   * Confirms a password reset.
   */
  confirmPasswordReset(data: PasswordResetConfirm): Promise<void>
  /**
   * Updates the current user's profile.
   */
  updateProfile(data: Partial<T>): Promise<T>
  /**
   * Changes the current user's password.
   */
  changePassword(oldPassword: string, newPassword: string): Promise<void>
  /**
   * Initializes auth state (e.g., from stored tokens).
   */
  initialize(): Promise<void>
  /**
   * Resolves when the session restore started by `initialize()` has settled — the point
   * after which the client knows whether this visitor is signed in.
   *
   * Resolves IMMEDIATELY when no restore is in flight: before `initialize()` is ever
   * called, and after it has finished. A restore that failed resolves too (it settled the
   * question), so an HTTP client can await this before every request without risking one
   * held forever. That is what makes the fetch-before-restore race impossible: a page that
   * fetches viewer-dependent data on mount waits here instead of going out anonymously
   * (see `setAuthGate` in `@molecule/app-http`).
   *
   * Optional: a provider that restores no session has nothing to wait for. Without it, an
   * HTTP client bonded to that provider sends first-paint requests unauthenticated.
   *
   * A provider whose restore sends a request THROUGH the gated HTTP client must send that
   * request with `skipAuthGate: true` (`RequestConfig` in `@molecule/app-http`): the gate
   * waits on this promise, so holding the restore's own request makes the gate wait on
   * itself and stalls every request it holds until it times out. `createJWTAuthClient`'s
   * restore does not need it — it uses `fetch`, not the bonded client.
   */
  whenRestored?(): Promise<void>
  /**
   * Subscribes to auth state changes.
   */
  subscribe(callback: (state: AuthState<T>) => void): () => void
  /**
   * Subscribes to auth state changes (alias for subscribe).
   */
  onAuthChange(callback: (state: AuthState<T>) => void): () => void
  /**
   * Gets the current access token (alias for getAccessToken).
   */
  getToken?(): string | null
  /**
   * Adds an auth event listener.
   */
  addEventListener(listener: AuthEventListener): () => void
  /**
   * Destroys the auth client.
   */
  destroy(): void
}

FormController

Form controller interface.

All form providers must implement this interface.

interface FormController<T extends Record<string, unknown> = Record<string, unknown>> {
  /**
   * Gets the current form state.
   */
  getState(): FormState<T>
  /**
   * Gets the value of a specific field.
   */
  getValue(name: string): unknown
  getValue<K extends keyof T>(name: K): T[K]
  /**
   * Gets all form values.
   */
  getValues(): T
  /**
   * Sets the value of a specific field.
   */
  setValue(
    name: string,
    value: unknown,
    options?: {
      shouldValidate?: boolean
      shouldDirty?: boolean
      shouldTouch?: boolean
    },
  ): void
  /**
   * Sets multiple values at once.
   */
  setValues(
    values: Partial<T>,
    options?: {
      shouldValidate?: boolean
    },
  ): void
  /**
   * Gets the error for a specific field.
   */
  getError(name: string): string | undefined
  /**
   * Sets the error for a specific field.
   */
  setError(name: string, error: string | undefined): void
  /**
   * Clears the error for a specific field.
   */
  clearError<K extends keyof T>(name: K): void
  /**
   * Clears all errors.
   */
  clearErrors(): void
  /**
   * Gets the field state for a specific field.
   */
  getFieldState<K extends keyof T>(name: K): FieldState<T[K]>
  /**
   * Registers a field for form management.
   */
  register(nameOrOptions: string | RegisterOptions, options?: RegisterOptions): FieldRegistration
  /**
   * Unregisters a field.
   */
  unregister(name: string): void
  /**
   * Validates a specific field.
   */
  validateField<K extends keyof T>(name: K): Promise<boolean>
  /**
   * Validates all fields.
   */
  validate(): Promise<boolean>
  /**
   * Resets the form to initial values.
   */
  reset(values?: Partial<T>): void
  /**
   * Handles form submission.
   */
  handleSubmit(
    onSubmit: (values: T) => void | Promise<void>,
    onError?: (errors: Partial<Record<keyof T, string>>) => void,
  ): (event?: { preventDefault?: () => void }) => Promise<void>
  /**
   * Sets focus to a field.
   */
  setFocus(name: keyof T): void
  /**
   * Subscribes to form state changes.
   */
  subscribe(callback: (state: FormState<T>) => void): () => void
  /**
   * Destroys the form controller.
   */
  destroy(): void
}

FormOptions

Form creation options.

interface FormOptions<T extends Record<string, unknown>> {
  /**
   * Default values.
   */
  defaultValues?: Partial<T>
  /**
   * Validation mode.
   */
  mode?: 'onSubmit' | 'onChange' | 'onBlur' | 'all'
  /**
   * Revalidation mode.
   */
  reValidateMode?: 'onChange' | 'onBlur' | 'onSubmit'
  /**
   * Whether to focus the first error field on submit.
   */
  shouldFocusError?: boolean
  /**
   * Form-level validation function.
   */
  validate?: (
    values: T,
  ) => Partial<Record<keyof T, string>> | Promise<Partial<Record<keyof T, string>>>
}

HttpClient

HTTP client interface.

All HTTP providers must implement this interface.

interface HttpClient {
  /**
   * Base URL for all requests.
   */
  baseURL: string
  /**
   * Default headers for all requests.
   */
  defaultHeaders: Record<string, string>
  /**
   * Makes a generic HTTP request.
   */
  request<T = unknown>(config: FullRequestConfig): Promise<HttpResponse<T>>
  /**
   * Makes a GET request.
   */
  get<T = unknown>(url: string, config?: RequestConfig): Promise<HttpResponse<T>>
  /**
   * Makes a POST request.
   */
  post<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
  /**
   * Makes a PUT request.
   */
  put<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
  /**
   * Makes a PATCH request.
   */
  patch<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
  /**
   * Makes a DELETE request.
   */
  delete<T = unknown>(url: string, config?: RequestConfig): Promise<HttpResponse<T>>
  /**
   * Adds a request interceptor.
   * Returns a function to remove the interceptor.
   */
  addRequestInterceptor(interceptor: RequestInterceptor): () => void
  /**
   * Adds a response interceptor.
   * Returns a function to remove the interceptor.
   */
  addResponseInterceptor(interceptor: ResponseInterceptor): () => void
  /**
   * Adds an error interceptor.
   * Returns a function to remove the interceptor.
   */
  addErrorInterceptor(interceptor: ErrorInterceptor): () => void
  /**
   * Sets the authorization token.
   */
  setAuthToken(token: string | null): void
  /**
   * Returns the current authorization token, or `null` if not set.
   */
  getAuthToken(): string | null
  /**
   * Registers a handler for authentication errors (401).
   *
   * @returns An unsubscribe function.
   */
  onAuthError(handler: () => void): () => void
}

Router

Client-side router providing navigation, guards, route matching, and history control.

All routing providers must implement this interface.

interface Router {
  /**
   * Returns the current route location (pathname, search, hash, state).
   */
  getLocation(): RouteLocation
  /**
   * Gets the current route params.
   */
  getParams<T extends RouteParams = RouteParams>(): T
  /**
   * Gets the current query params.
   */
  getQuery(): QueryParams
  /**
   * Gets a specific query parameter.
   */
  getQueryParam(key: string): string | undefined
  /**
   * Gets the current hash.
   */
  getHash(): string
  /**
   * Navigates to a path.
   */
  navigate(path: string, options?: NavigateOptions): void
  /**
   * Navigates to a named route.
   */
  navigateTo(
    name: string,
    params?: RouteParams,
    query?: QueryParams,
    options?: NavigateOptions,
  ): void
  /**
   * Goes back in history.
   */
  back(): void
  /**
   * Goes forward in history.
   */
  forward(): void
  /**
   * Goes to a specific point in history.
   */
  go(delta: number): void
  /**
   * Updates the current query params.
   */
  setQuery(params: QueryParams, options?: NavigateOptions): void
  /**
   * Updates a specific query parameter.
   */
  setQueryParam(key: string, value: string | undefined, options?: NavigateOptions): void
  /**
   * Updates the current hash.
   */
  setHash(hash: string, options?: NavigateOptions): void
  /**
   * Checks if a path matches the current location.
   *
   * @returns `true` if the path matches the current route.
   */
  isActive(path: string, exact?: boolean): boolean
  /**
   * Matches a path pattern against a pathname.
   */
  matchPath<Params extends RouteParams = RouteParams>(
    pattern: string,
    pathname: string,
  ): RouteMatch<Params> | null
  /**
   * Generates a URL from a named route.
   */
  generatePath(name: string, params?: RouteParams, query?: QueryParams): string
  /**
   * Subscribes to route changes.
   */
  subscribe(listener: RouteChangeListener): () => void
  /**
   * Adds a navigation guard.
   */
  addGuard(guard: NavigationGuard): () => void
  /**
   * Registers route definitions.
   */
  registerRoutes(routes: RouteDefinition[]): void
  /**
   * Gets all registered routes.
   */
  getRoutes(): RouteDefinition[]
  /**
   * Destroys the router.
   */
  destroy(): void
}

RouterConfig

Configuration options for creating a router instance.

interface RouterConfig {
  /**
   * Router mode.
   */
  mode?: 'history' | 'hash' | 'memory'
  /**
   * Base path.
   */
  basePath?: string
  /**
   * Initial routes.
   */
  routes?: RouteDefinition[]
}

StoreConfig

Configuration for creating a store (initial state, optional name, and middleware chain).

interface StoreConfig<T> {
  /**
   * Initial state value.
   */
  initialState: T
  /**
   * Optional name for debugging.
   */
  name?: string
  /**
   * Optional middleware functions.
   */
  middleware?: StoreMiddleware<T>[]
}

Store

Reactive state container with getState, setState, subscribe, and destroy.

All state management providers must implement this interface.

interface Store<T> {
  /**
   * Gets the current state.
   */
  getState(): T
  /**
   * Sets the state (partial or via updater function).
   */
  setState(partial: Partial<T> | ((state: T) => Partial<T>)): void
  /**
   * Subscribes to state changes.
   * Returns an unsubscribe function.
   */
  subscribe(listener: StateListener<T>): () => void
  /**
   * Destroys the store and cleans up subscriptions.
   */
  destroy(): void
}

Theme

Complete theme definition.

interface Theme {
  name: string
  mode: 'light' | 'dark'
  colors: ThemeColors
  breakpoints: ThemeBreakpoints
  spacing: ThemeSpacing
  typography: ThemeTypography
  borderRadius: ThemeBorderRadius
  shadows: ThemeShadows
  transitions: ThemeTransitions
  zIndex: ThemeZIndex
}

UseBackHandlerOptions

Options for the useBackHandler hook.

interface UseBackHandlerOptions {
  /** Whether the handler is enabled. Defaults to true. */
  enabled?: boolean
}

UseAppStateResult

Result from the useAppState hook.

interface UseAppStateResult {
  /** Current app state: 'active' | 'background' | 'inactive' */
  appState: string
  /** Whether the app is in the foreground */
  isActive: boolean
}

UseKeyboardHeightResult

Result from the useKeyboardHeight hook.

interface UseKeyboardHeightResult {
  /** Current keyboard height in points (0 when hidden) */
  keyboardHeight: number
  /** Whether the keyboard is currently visible */
  isKeyboardVisible: boolean
}

AgentIdentity

Display identity for the AI coding agent and the host product, used to interpolate the {{agentName}} / {{productName}} tokens in shared chat/IDE copy. A consuming app sets these to its own agent + product brand names; the shared packages fall back to DEFAULT_AGENT_IDENTITY when it does not.

interface AgentIdentity {
  /** Display name of the AI coding agent. Defaults to `DEFAULT_AGENT_NAME`. */
  agentName: string
  /** Display name of the host product / IDE. Defaults to `DEFAULT_PRODUCT_NAME`. */
  productName: string
}

UseAIModelsResult

Result returned by useAIModels.

interface UseAIModelsResult {
  /** Available models, or an empty array while loading. */
  models: AppModelDefinition[]
  /**
   * Per-mode server default model ids for the requester's tier, or `undefined`
   * while loading or on servers that don't provide them.
   */
  defaults: AppModeModelDefaults | undefined
  /** The single model marked `freeTier: true`, or `undefined`. */
  freeTierModel: AppModelDefinition | undefined
  /** `true` while the initial fetch is in flight. */
  loading: boolean
  /** Error from the initial fetch, or `null`. */
  error: Error | null
}

UseChangePasswordReturn

Return type for useChangePassword hook.

interface UseChangePasswordReturn {
  status: UsePromiseState<void>['status']
  error: UsePromiseState<void>['error']
  changePassword: (oldPassword: string, newPassword: string) => Promise<void>
  reset: () => void
}

UseDeviceResult

Hook return type.

interface UseDeviceResult {
  deviceInfo: DeviceInfo
  screenInfo: ScreenInfo
  hardwareInfo: HardwareInfo
  featureSupport: FeatureSupport
  supports: (feature: keyof FeatureSupport) => boolean
  isOnline: () => boolean
  isStandalone: () => boolean
  language: string
  languages: string[]
}

UseFormOptions

Options for useForm hook.

interface UseFormOptions<T extends Record<string, unknown>> extends FormOptions<T> {
  /**
   * Form provider's createForm function.
   */
  createForm: (options: FormOptions<T>) => FormController<T>
}

UseFormResult

Result of useForm hook.

interface UseFormResult<T extends Record<string, unknown>> {
  formState: FormState<T>
  isValid: boolean
  isDirty: boolean
  isSubmitting: boolean
  register: (name: keyof T, options?: RegisterOptions) => FieldRegistration
  getValue: <K extends keyof T>(name: K) => T[K]
  setValue: <K extends keyof T>(name: K, value: T[K]) => void
  getError: (name: keyof T) => string | undefined
  setError: (name: keyof T, error: string | undefined) => void
  clearErrors: () => void
  handleSubmit: (onSubmit: (values: T) => void | Promise<void>) => (event?: React.FormEvent) => void
  reset: (values?: Partial<T>) => void
  validate: () => Promise<boolean>
}

UseHttpState

State for async HTTP operations.

interface UseHttpState<T> {
  data: T | null
  loading: boolean
  error: Error | null
}

UseHttpResult

Result of useHttp hook.

interface UseHttpResult<T> extends UseHttpState<T> {
  execute: () => Promise<T | null>
  reset: () => void
}

UseHttpOptions

Options for useHttp hook.

interface UseHttpOptions<T> extends RequestConfig {
  /**
   * Whether to execute the request immediately on mount.
   */
  immediate?: boolean
  /**
   * Callback when request succeeds.
   */
  onSuccess?: (data: T) => void
  /**
   * Callback when request fails.
   */
  onError?: (error: Error) => void
}

UseLoginReturn

Return type for useLogin hook.

interface UseLoginReturn<T = unknown> {
  status: UsePromiseState<AuthResult<T>>['status']
  value: UsePromiseState<AuthResult<T>>['value']
  error: UsePromiseState<AuthResult<T>>['error']
  login: (credentials: LoginCredentials) => Promise<AuthResult<T>>
  reset: () => void
}

UseOAuthReturn

Return type for useOAuth hook.

interface UseOAuthReturn {
  providers: string[]
  getOAuthUrl: (provider: string) => string
  /** Full-page redirect to the provider (default). The opener page navigates away. */
  redirect: (provider: string) => void
  /**
   * Open the provider in a popup so the opener page does NOT navigate. On success
   * the session is established in the opener in place and `config.onSuccess` fires;
   * on failure `config.onError` fires. Falls back to a full-page `redirect`
   * when the popup is blocked.
   */
  loginViaPopup: (provider: string) => void
}

UsePasswordResetReturn

Return type for usePasswordReset hook.

interface UsePasswordResetReturn {
  requestStatus: UsePromiseState<void>['status']
  requestError: UsePromiseState<void>['error']
  confirmStatus: UsePromiseState<void>['status']
  confirmError: UsePromiseState<void>['error']
  requestReset: (data: PasswordResetRequest) => Promise<void>
  confirmReset: (data: PasswordResetConfirm) => Promise<void>
  reset: () => void
}

UsePlatformResult

Hook return type.

interface UsePlatformResult {
  platform: Platform
  isNative: boolean
  isMobile: boolean
  isDesktop: boolean
  isWeb: boolean
  isDevelopment: boolean
  isProduction: boolean
  isPlatform: (...platforms: Platform[]) => boolean
}

UsePromiseState

Extended promise state with actions.

interface UsePromiseState<T> {
  status: PromiseStatus
  value: T | null
  error: Error | null
  cancel: (message?: string) => void
  reset: () => void
}

UsePushResult

Hook return type.

interface UsePushResult {
  permission: PermissionStatus | null
  token: PushToken | null
  checkPermission: () => Promise<PermissionStatus>
  requestPermission: () => Promise<PermissionStatus>
  register: (options?: PushRegisterOptions) => Promise<PushToken>
  unregister: () => Promise<void>
  onNotificationReceived: (listener: NotificationReceivedListener) => () => void
  onNotificationAction: (listener: NotificationActionListener) => () => void
  onTokenChange: (listener: TokenChangeListener) => () => void
  setBadge: (count: number) => Promise<void>
  clearBadge: () => Promise<void>
}

UsePushOptions

Options for the usePush hook (e.g. check permission on mount).

interface UsePushOptions {
  /**
   * Whether to check permission status on mount.
   */
  checkOnMount?: boolean
}

UseSignupReturn

Return type for useSignup hook.

interface UseSignupReturn<T = unknown> {
  status: UsePromiseState<AuthResult<T>>['status']
  value: UsePromiseState<AuthResult<T>>['value']
  error: UsePromiseState<AuthResult<T>>['error']
  signup: (data: RegisterData) => Promise<AuthResult<T>>
  reset: () => void
}

UseStorageValueOptions

Options for useStorageValue hook.

interface UseStorageValueOptions<T> {
  /**
   * Default value if key doesn't exist.
   */
  defaultValue?: T
  /**
   * Whether to sync across tabs/windows (if supported by storage provider).
   */
  sync?: boolean
}

UseStorageValueResult

Result of useStorageValue hook.

interface UseStorageValueResult<T> {
  value: T | undefined
  setValue: (value: T) => Promise<void>
  removeValue: () => Promise<void>
  loading: boolean
  error: Error | null
}

UseVerifyPaymentReturnOptions

Options for useVerifyPaymentReturn.

interface UseVerifyPaymentReturnOptions {
  /**
   * Provider name to verify with, when the return URL carries no `provider`
   * query parameter. Leave unset to verify only what the URL names.
   */
  provider?: string
  /** Set `false` to skip verification entirely (e.g. behind a feature flag). */
  enabled?: boolean
  /**
   * Remove the provider's query parameters from the address bar once the
   * purchase is verified, so a reload (or a shared link) cannot replay the
   * verification. Defaults to `true`.
   */
  cleanUrl?: boolean
  /** Called once, after the purchase verifies. */
  onVerified?: () => void
  /** Called when verification fails. */
  onError?: (error: Error) => void
}

UseVerifyPaymentReturnResult

State of the post-checkout verification.

interface UseVerifyPaymentReturnResult {
  /**
   * `idle` when this page load is not a checkout return (no transaction id in
   * the URL) or auth is still hydrating; `verifying` while the API call is in
   * flight; then `verified` or `failed`.
   */
  status: VerifyPaymentReturnStatus
  /** `true` when the URL identifies a purchase to verify. */
  isReturn: boolean
  /** The provider named by the URL (or the `provider` option). */
  provider: string | null
  /** The provider transaction/session id read from the URL. */
  transactionId: string | null
  /** Why verification failed, when it did. */
  error: Error | null
  /** Re-run the verification — wire this to a retry button. */
  retry: () => void
}

UseVersionResult

Hook return type.

interface UseVersionResult {
  state: VersionState
  isUpdateAvailable: boolean
  isChecking: boolean
  isServiceWorkerWaiting: boolean
  newVersion: string | undefined
  checkForUpdates: () => Promise<boolean>
  applyUpdate: (options?: { force?: boolean }) => void
  dismissUpdate: () => void
  startPeriodicChecks: (options?: UpdateCheckOptions) => void
  stopPeriodicChecks: () => void
}

ProviderProps

Props for provider components.

interface ProviderProps {
  children: ReactNode
}

StateProviderProps

Props for state provider component.

interface StateProviderProps extends ProviderProps {
  provider: StateProvider
}

AuthProviderProps

Props for auth provider component.

interface AuthProviderProps<T = unknown> extends ProviderProps {
  client: AuthClient<T>
}

ThemeProviderProps

Props for theme provider component.

interface ThemeProviderProps extends ProviderProps {
  provider: ThemeProvider
  initialTheme?: string
}

RouterProviderProps

Props for router provider component.

interface RouterProviderProps extends ProviderProps {
  router: Router
}

I18nProviderProps

Props for i18n provider component.

interface I18nProviderProps extends ProviderProps {
  provider: I18nProvider
}

HttpProviderProps

Props for http provider component.

interface HttpProviderProps extends ProviderProps {
  client: HttpClient
}

StorageProviderProps

Props for storage provider component.

interface StorageProviderProps extends ProviderProps {
  provider: StorageProvider
}

LoggerProviderProps

Props for logger provider component.

interface LoggerProviderProps extends ProviderProps {
  provider: LoggerProvider
}

ChatProviderProps

Props for the ChatProvider React component.

interface ChatProviderProps extends ProviderProps {
  provider: ChatProvider
}

WorkspaceProviderProps

Props for workspace provider component.

interface WorkspaceProviderProps extends ProviderProps {
  provider: WorkspaceProvider
}

EditorProviderProps

Props for editor provider component.

interface EditorProviderProps extends ProviderProps {
  provider: EditorProvider
}

PreviewProviderProps

Props for preview provider component.

interface PreviewProviderProps extends ProviderProps {
  provider: PreviewProvider
}

MoleculeProviderProps

Properties for molecule provider.

interface MoleculeProviderProps extends ProviderProps {
  state?: StateProvider
  auth?: AuthClient<unknown>
  theme?: ThemeProvider
  router?: Router
  i18n?: I18nProvider
  http?: HttpClient
  storage?: StorageProvider
  logger?: LoggerProvider
  chat?: ChatProvider
  workspace?: WorkspaceProvider
  editor?: EditorProvider
  preview?: PreviewProvider
}

UseStoreOptions

Hook options for useStore.

interface UseStoreOptions<T, S> {
  selector?: (state: T) => S
  equalityFn?: (a: S, b: S) => boolean
}

UseAuthOptions

Hook options for useAuth.

interface UseAuthOptions {
  /**
   * Whether to automatically refresh the token on mount.
   */
  autoRefresh?: boolean
}

UseAuthResult

Hook result for useAuth.

interface UseAuthResult<T = unknown> {
  state: AuthState<T>
  login: AuthClient<T>['login']
  logout: AuthClient<T>['logout']
  register: AuthClient<T>['register']
  refresh: AuthClient<T>['refresh']
  setUser: AuthClient<T>['setUser']
  isAuthenticated: boolean
  isLoading: boolean
  user: T | null
}

UseThemeResult

Hook result for useTheme.

interface UseThemeResult {
  theme: Theme
  themeName: string
  setTheme: (name: string) => void
  toggleTheme: () => void
  mode: 'light' | 'dark'
}

UseRouterResult

Hook result for useRouter.

interface UseRouterResult {
  location: Router['getLocation'] extends () => infer R ? R : never
  params: Record<string, string>
  query: QueryParams
  navigate: Router['navigate']
  navigateTo: Router['navigateTo']
  back: Router['back']
  forward: Router['forward']
  isActive: Router['isActive']
}

UseTranslationResult

Hook result for useTranslation.

interface UseTranslationResult {
  t: I18nProvider['t']
  locale: string
  setLocale: I18nProvider['setLocale']
  locales: ReturnType<I18nProvider['getLocales']>
  formatNumber: I18nProvider['formatNumber']
  formatDate: I18nProvider['formatDate']
  direction: 'ltr' | 'rtl'
}

UseChatOptions

Hook options for useChat.

interface UseChatOptions {
  /** Chat endpoint (e.g., '/projects/123/chat'). */
  endpoint: string
  /** Project ID for context. */
  projectId?: string
  /**
   * Display name of the AI coding agent, interpolated into user-facing chat
   * copy (e.g. the stalled-stream notice). The host passes its own agent brand
   * name; defaults to the neutral `DEFAULT_AGENT_NAME` so the shared hook never
   * names a specific product.
   */
  agentName?: string
  /** Load history on mount. */
  loadOnMount?: boolean
  /**
   * This client may only WATCH the conversation (e.g. a read-only project
   * viewer): the hook never issues chat POSTs on its behalf — no resume
   * request after a reload, no auto-retries. A live turn is followed through
   * the remote-watch path instead: pushed broadcast frames (applyRemoteEvent)
   * render it in real time and the history reconcile poll backstops gaps, with
   * `isRemoteStreaming` driving the activity indicator.
   */
  readOnly?: boolean
  /** Called when a file is created or modified by a tool call (path + new content). */
  onFileChange?: (path: string, content: string) => void
  /** Called when the AI switches between plan and execute modes. */
  onModeChange?: (mode: 'plan' | 'execute') => void
  /** Called when the backend assigns or confirms a conversation ID. */
  onConversationId?: (id: string) => void
  /** Called for every streaming event — useful for notifications, sounds, etc. */
  onStreamEvent?: (event: ChatStreamEvent) => void
}

SendMessageOptions

Options for UseChatResult.sendMessage.

interface SendMessageOptions {
  /**
   * Skip the optimistic local user-message bubble. The text is still sent to
   * the server. Used for ask_user responses: the answer is folded into the
   * ask_user tool card (a checkmark on the chosen option, or the custom text
   * shown in-card) rather than echoed as a separate message below it.
   */
  suppressUserMessage?: boolean
  /**
   * Mark this send as issued automatically on the user's behalf (e.g. an
   * auto-fix prompt). The optimistic local bubble and the persisted message are
   * flagged `automatic` so the chat renders it in the distinct auto-sent style
   * (agent avatar + accent border) instead of looking like the user typed it.
   */
  automatic?: boolean
  /**
   * Mark this send as the answer to the pending `ask_user` question. The most
   * recent unanswered `ask_user` tool call in the store is resolved in place —
   * its `output` is set to this answer — so the chosen option stays checked
   * across remounts (e.g. the discovery→IDE transition) instead of relying on
   * ephemeral component state that the answer's selection would otherwise lose.
   * Distinct from `suppressUserMessage` (which the post-boot kickoff also
   * sets) so resolving never misfires on a non-ask_user suppressed send.
   */
  askUserAnswer?: boolean
  /**
   * Mark an `automatic` send as directly requested by the user (e.g. the
   * editor's "Fix with AI" action, the broken-preview overlay's "Fix with AI"
   * button) rather than dispatched autonomously by the platform. A user Stop
   * suppresses autonomous automatic sends until the user re-engages; a
   * user-initiated one IS that re-engagement — it clears the stop and sends.
   */
  userInitiated?: boolean
  /**
   * Send on the SIDE CHANNEL: a human-to-human message (e.g. a team note) the
   * server intercepts before running any agent turn. When the provider supports
   * `sendSideMessage`, the send goes out IMMEDIATELY on an independent request —
   * it never queues behind an active turn, never takes over the streaming
   * state, and never tears down remote-turn tracking (a viewer's note while
   * watching a teammate's turn must not stop the watching). Falls back to the
   * normal send path on providers without side-channel support.
   */
  sideChannel?: boolean
  /**
   * Mark this send as composed through voice dictation — the mic button's
   * transcript was still present in the composer at submit. The optimistic
   * bubble and the persisted message are flagged `viaDictation` so the chat
   * renders a mic badge on the message, live and after a reload.
   */
  viaDictation?: boolean
}

UseChatResult

Hook result for useChat.

interface UseChatResult {
  messages: ChatMessage[]
  isLoading: boolean
  /**
   * True while a backend turn for this conversation streams WITHOUT this client
   * owning the request — a turn started in another tab, by a teammate, or any
   * server-side continuation. Detected from pushed (broadcast) chat events and
   * confirmed/cleared against the server's `streaming` history flag, so the Stop
   * control can stay visible and functional whenever ANY backend turn is live —
   * not only for sends this hook instance made.
   */
  isRemoteStreaming: boolean
  /**
   * Tell the hook a pushed (broadcast) chat event arrived for this conversation.
   * The host (ChatPanel) calls this from its push-channel handler; the hook then
   * confirms against the server's `streaming` flag and, while a remote turn is
   * live, keeps `isRemoteStreaming` true until the server reports it finished.
   */
  noteRemoteStreamEvent: () => void
  error: string | null
  /**
   * Metadata about a limit-related error, for a contextual call-to-action.
   * `limitType` names the RULE the backend enforced; `billingAction` names the
   * REMEDY it resolved (e.g. `add_funds`, `add_payment_method`,
   * `raise_spend_cap`, `upgrade`, `none`) and is what the button should be
   * built from — the same limit needs a different button per account.
   * `upgradeTier` is the plan an upgrade would move to, explicitly `null` when
   * there is no higher tier. The backend owns these vocabularies, so the
   * action/tier are plain strings here.
   */
  errorMeta: {
    limitType?: string
    requiresSignup?: boolean
    billingAction?: string
    upgradeTier?: string | null
  } | null
  /** Current agent mode — plan (read-only research) or execute (full access). */
  mode: 'plan' | 'execute'
  /**
   * Whether the conversation runs at the provider's fast/priority speed tier
   * (server-persisted per conversation; hydrated from the history load's
   * `fastMode` meta field, when the server provides one). Only meaningful for
   * models that support a fast tier — the server ignores it otherwise.
   */
  fastMode: boolean
  /**
   * Transient label for a background phase (e.g. the post-response verification
   * pass — "Type-checking the API", "Linting"), set by `status` stream events.
   * The UI shows it in place of the spinner's generic rotating messages; `null`
   * when no such phase is active.
   */
  streamingStatus: string | null
  /**
   * Commands the executor detached with `run_in_background`, newest last. Each
   * appears here the moment it starts and is replaced in place when it finishes,
   * so the UI can show work that outlives the tool call that started it.
   */
  backgroundTasks: BackgroundTaskState[]
  /**
   * Active 5XX backoff-retry countdown, or `null` when none is pending. After a
   * backend server error (HTTP 5XX) the hook does NOT surface a terminal error —
   * it shows this cancelable countdown and, when it elapses, auto-resumes the
   * turn where the user left off (`resume:true`). `secondsRemaining` ticks down
   * once per second; `attempt` is the 1-based retry number (capped at 3). 4XX,
   * limit/quota, and signup-required errors never auto-retry.
   */
  retryCountdown: {
    secondsRemaining: number
    attempt: number
  } | null
  /** Update the local mode state (for instant mode toggle without an AI turn). */
  setMode: (mode: 'plan' | 'execute') => void
  /** Update the local fast-mode state (for instant toggle without an AI turn). */
  setFastMode: (fastMode: boolean) => void
  sendMessage: (
    message: string,
    attachments?: ChatAttachment[],
    options?: SendMessageOptions,
  ) => Promise<void>
  abort: () => void
  /**
   * Cancel a pending 5XX auto-retry. Clears the countdown and surfaces the
   * original error (via `error`) so the user sees why the turn failed.
   */
  cancelRetry: () => void
  clearHistory: () => Promise<void>
  /** Edit the content of a queued (not yet sent) message. */
  editQueuedMessage: (msgId: string, newContent: string) => void
  /** Remove a queued (not yet sent) message from the queue. */
  deleteQueuedMessage: (msgId: string) => void
  /** Remove queued auto-fix messages whose content references the given file path. */
  clearQueuedForFile: (filePath: string) => void
  /**
   * Append an inline transcript card (model / mode / skills / custom notice) as a
   * `role:'system'` card-message in the ONE message store. Used by the host (ChatPanel)
   * to render a TEAMMATE's broadcast `card` event live — this client's OWN cards arrive
   * through the stream and are appended internally. De-duped by the server-assigned id.
   */
  appendCardMessage: (
    id: string,
    timestamp: number,
    card: NonNullable<ChatMessage['cardEvent']>,
  ) => void
  /**
   * Append a COMPLETE, non-streaming chat message (a `message` stream event — e.g.
   * a teammate's human-only team note) to the ONE message store. Used by the host
   * (ChatPanel) to render a TEAMMATE's broadcast `message` event live — this
   * client's OWN `message` events arrive through the stream and are appended
   * internally. De-duped by the server-assigned message id.
   */
  appendCompleteMessage: (message: ChatMessage) => void
  /**
   * Ingest ONE pushed (broadcast) stream frame from a turn running elsewhere —
   * a teammate's send, another tab, a server-side continuation — into the ONE
   * message store, through the same content applier as an own SSE stream: text/
   * thinking deltas, tool events, verification, cards, complete messages, done.
   * The host (ChatPanel) calls this from its push-channel handler for every
   * broadcast frame of the OPEN conversation. Own echoes are dropped while a
   * local send is in flight (the SSE stream is authoritative for the sender);
   * complete id-carrying items (cards, team notes) always apply, de-duped.
   */
  applyRemoteEvent: (event: ChatStreamEvent) => void
  /**
   * Reload history and converge the local view on the server transcript (and
   * re-enter a still-streaming turn). The page-lifecycle events run this
   * automatically; the host should ALSO call it whenever its chat push channel
   * (re)connects — a broadcast sent while that socket was down (a teammate's
   * team note against a backgrounded tab or a slept laptop) is otherwise lost
   * until the next lifecycle event happens to fire. Cheap when nothing changed:
   * an identical transcript is never re-applied.
   */
  reconcileHistory: () => Promise<void>
}

UseWorkspaceResult

Hook result for useWorkspace.

interface UseWorkspaceResult {
  layout: WorkspaceLayout
  activePanel: PanelId | null
  collapsedPanels: Set<PanelId>
  togglePanel: (panelId: PanelId) => void
  resizePanel: (panelId: PanelId, size: number) => void
  setActivePanel: (panelId: PanelId) => void
  resetLayout: () => void
}

UseEditorResult

Hook result for useEditor.

interface UseEditorResult {
  tabs: EditorTab[]
  activeFile: string | null
  openFile: (file: EditorFile) => void
  closeFile: (path: string) => void
  getContent: () => string | null
  setContent: (path: string, content: string) => void
  setActiveTab: (path: string) => void
  mount: EditorProvider['mount']
  dispose: () => void
  focus: () => void
  openDiff: (file: DiffFile) => void
  closeDiff: () => void
  pinTab: (path: string) => void
  addExtraLib: (content: string, filePath: string) => void
  onFixWithAI: (callback: (request: FixWithAIRequest) => void) => () => void
}

UsePreviewResult

Hook result for usePreview.

interface UsePreviewResult {
  state: PreviewState
  setUrl: (url: string) => void
  refresh: () => void
  setDevice: (device: DeviceFrame) => void
  openExternal: () => void
  /**
   * Records a navigation the running preview reported via its `molecule:navigate`
   * message — updates the displayed current location without reloading the iframe.
   * Pass `isReplace` when the preview REPLACED its current history entry (a
   * `replaceState` redirect/canonicalization) so the forward stack is preserved
   * instead of truncated (a `pushState`, the default, truncates forward).
   */
  recordNavigation: (url: string, isReplace?: boolean) => void
  /** Navigates the preview to the previous navigation-history entry (Back). */
  back: () => void
  /** Navigates the preview to the next navigation-history entry (Forward). */
  forward: () => void
}

Types

AsyncSetState

Async-capable setState function.

type AsyncSetState<T> = (value: T | ((prev: T) => T) | Promise<T | ((prev: T) => T)>) => void
  • value — The new state value, an updater function receiving previous state, or a Promise resolving to either.

AsyncExtendState

Async-capable extendState function for partial updates.

type AsyncExtendState<T> = (
  partial: Partial<T> | ((prev: T) => Partial<T>) | Promise<Partial<T> | ((prev: T) => Partial<T>)>,
) => void

UseCapacitorAppResult

Hook return type.

type UseCapacitorAppResult = CapacitorAppState & {
  initialize: () => Promise<void>
}

VerifyPaymentReturnStatus

How far the return-page verification has got.

type VerifyPaymentReturnStatus = 'idle' | 'verifying' | 'verified' | 'failed'

Functions

useAppState()

Tracks whether the app is in the foreground, background, or inactive.

Uses React Native's AppState API under the hood. Falls back to 'active' on platforms where AppState is unavailable.

function useAppState(): UseAppStateResult

Returns: Current app state and whether the app is active.

useBackHandler(handler, options)

Registers a handler for the Android hardware back button.

Return true from the handler to prevent the default back behavior, or false to allow it.

function useBackHandler(handler: () => boolean, options?: UseBackHandlerOptions): void
  • handler — Callback invoked when the hardware back button is pressed.
  • options — Optional configuration.

useKeyboardHeight()

Tracks soft keyboard visibility and height.

Uses React Native's Keyboard API. Falls back to hidden state on platforms where Keyboard is unavailable.

function useKeyboardHeight(): UseKeyboardHeightResult

Returns: Current keyboard height and visibility state.

useSafeArea()

Returns the current safe area insets from react-native-safe-area-context.

Must be used within a SafeAreaProvider. Falls back to zero insets if the context is unavailable.

function useSafeArea(): SafeAreaInsets

Returns: Safe area insets for the current device.

resetAIModelsCache()

Test-only: drops every cached model list so the next useAIModels call refetches. Exposed for unit tests; do not call from production code.

function resetAIModelsCache(): void

useAIModels(projectId)

Subscribes to the cached AI model catalog. The first mount of a scope triggers a single GET /ai/models fetch; subsequent mounts return the cached result.

function useAIModels(projectId?: string): UseAIModelsResult
  • projectId — Optional project scope: includes that project's custom ("bring your own AI") models on servers that support them.

Returns: Models, free-tier model, loading flag, and error.

useAuthClient()

Hook to access the auth client from context.

function useAuthClient(): AuthClient<T>

Returns: The auth client from context

useAuth(options)

Hook for authentication state and actions.

function useAuth(options?: UseAuthOptions): UseAuthResult<T>
  • options — Hook options

Returns: Auth state and action methods

useUser()

Hook to get just the authenticated user.

function useUser(): T | null

Returns: The authenticated user or null

useIsAuthenticated()

Hook to check if user is authenticated.

function useIsAuthenticated(): boolean

Returns: Whether the user is authenticated

useCapacitorApp(options)

Hook for Capacitor app initialization and state management.

Creates a CapacitorApp coordinator on mount, subscribes to state changes, and auto-initializes. Cleans up listeners on unmount via destroy().

function useCapacitorApp(options?: CapacitorAppOptions): UseCapacitorAppResult
  • options — Capacitor app configuration options

Returns: Current app state and an initialize function for manual re-initialization

useChangePassword()

Hook for changing password with async state tracking.

function useChangePassword(): UseChangePasswordReturn

Returns: Change password state and action

convergeHistory(prev, history)

Converge a live store on a fresh server history WITHOUT rewinding anything already on screen. This is the ONE place a server transcript is applied to a local view — the page-lifecycle/push reconcile, the remote-turn poll, the dropped-stream reconcile and the resume poll all go through it, because two paths that almost agree is how a message came to vanish and come back (reported 2026-09-21).

Per message id the further-along copy wins (messageProgress); a TIE keeps the local copy, so an unchanged transcript returns the same object references and a poll neither churns React nor rewinds. Messages only the server has are added in the server's order (filling gaps a watcher missed); messages only the store has (localOnlyMessages — an answer still carrying its local id, a session-local card, a turn the server has not persisted yet) are kept after them.

function convergeHistory(prev: ChatMessage[], history: ChatMessage[]): ChatMessage[]
  • prev — The store's current messages.
  • history — The messages from the server's history endpoint.

Returns: The converged message list.

localOnlyMessages(prev, history)

The messages only the local store holds, given a server history: optimistic bubbles and session-local cards, minus the optimistic ECHO of a send the server already persisted. A local user message carries a local id (user-N), the server's copy a server id, so ids never match — content does. Without this, the dashboard's first prompt (auto-sent by the workspace, then merged back in from history by the remote-stream poll) rendered as two identical user bubbles in every new project (2026-09-08).

function localOnlyMessages(prev: ChatMessage[], history: ChatMessage[]): ChatMessage[]
  • prev — The store's current messages.
  • history — The server's history.

Returns: The local-only messages to keep after the merged history.

resetChatStoresForTests()

Test-only: clear all conversation stores. The store is module-level (it must outlive component mounts), so it persists across test cases — reset it in a beforeEach the same way tests clear sessionStorage.

function resetChatStoresForTests(): void

useChatProvider()

Access the chat provider from context.

function useChatProvider(): ChatProvider

Returns: The ChatProvider instance from the nearest ChatContext.

useChat(options)

Hook for AI chat with streaming support.

Manages message state, sends messages to the backend, and handles SSE streaming responses.

function useChat(options: UseChatOptions): UseChatResult
  • options — Chat configuration including endpoint URL, project ID, and whether to load history on mount.

Returns: Chat state and controls: messages, isLoading, error, sendMessage, abort, and clearHistory.

useDevice()

Hook for device information.

Uses module-level getProvider() — device info is a singleton, not context-provided. Device info is static and doesn't change at runtime, so this uses useMemo.

function useDevice(): UseDeviceResult

Returns: Device information and utility methods

useEditorProvider()

Access the editor provider from context.

function useEditorProvider(): EditorProvider

Returns: The EditorProvider instance from the nearest EditorContext.

useEditor()

Hook for code editor management.

function useEditor(): UseEditorResult

Returns: Editor state and controls: tabs, activeFile, openFile, closeFile, getContent, setContent, setActiveTab, mount, dispose, and focus.

useForm(options)

Hook for form state management.

function useForm(options: UseFormOptions<T>): UseFormResult<T>
  • options — Form options including createForm from a forms provider

Returns: Form state and methods

useWatch(form, name)

Hook to watch a specific field value.

function useWatch(form: FormController<T>, name: K): T[K]
  • form — Form controller
  • name — Field name to watch

Returns: Current field value

useFieldState(form, name)

Hook to get field-level state.

function useFieldState(form: FormController<T>, name: keyof T): FieldState<T[keyof T]>
  • form — Form controller
  • name — Field name

Returns: Field state (value, error, touched, dirty, valid)

useHttpClient()

Hook to access the HTTP client from context.

function useHttpClient(): HttpClient

Returns: The HTTP client from context

useHttp(method, url, options)

Hook for making HTTP requests with state management.

function useHttp(
  method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',
  url: string,
  options?: UseHttpOptions<T>,
): UseHttpResult<T>
  • method — HTTP method
  • url — Request URL
  • options — Request options

Returns: Request state and execute function

useGet(url, options)

Hook for GET requests.

function useGet(url: string, options?: UseHttpOptions<T>): UseHttpResult<T>
  • url — Request URL to fetch from.
  • options — HTTP request options including callbacks and request config.

Returns: Request state (data, loading, error) and controls (execute, reset).

usePost(url, options)

Hook for POST requests.

function usePost(url: string, options?: UseHttpOptions<T>): UseHttpResult<T>
  • url — Request URL to post to.
  • options — HTTP request options including body data and callbacks.

Returns: Request state (data, loading, error) and controls (execute, reset).

usePut(url, options)

Hook for PUT requests.

function usePut(url: string, options?: UseHttpOptions<T>): UseHttpResult<T>
  • url — Request URL to send the PUT request to.
  • options — HTTP request options including body data and callbacks.

Returns: Request state (data, loading, error) and controls (execute, reset).

usePatch(url, options)

Hook for PATCH requests.

function usePatch(url: string, options?: UseHttpOptions<T>): UseHttpResult<T>
  • url — Request URL to send the PATCH request to.
  • options — HTTP request options including partial body data and callbacks.

Returns: Request state (data, loading, error) and controls (execute, reset).

useDelete(url, options)

Hook for DELETE requests.

function useDelete(url: string, options?: UseHttpOptions<T>): UseHttpResult<T>
  • url — Request URL of the resource to delete.
  • options — HTTP request options including callbacks.

Returns: Request state (data, loading, error) and controls (execute, reset).

useLoggerProvider()

Hook to access the logger provider from context.

function useLoggerProvider(): LoggerProvider

Returns: The logger provider from context

useLogger(name, config)

Hook to get a logger instance.

function useLogger(name: string, config?: Partial<LoggerConfig>): Logger
  • name — Logger name (usually component or module name)
  • config — Optional logger configuration

Returns: Logger instance

useRootLogger()

Hook to get the root logger.

function useRootLogger(): Logger

Returns: Root logger instance

useChildLogger(parentName, context)

Hook to create a child logger with additional context.

function useChildLogger(parentName: string, context: Record<string, unknown>): Logger
  • parentName — Parent logger name
  • context — Additional context to include in logs

Returns: Child logger instance

useLogin()

Hook for login with async state tracking.

function useLogin(): UseLoginReturn<T>

Returns: Login state and action

useOAuth(config)

Hook for OAuth authentication.

Reads OAuth configuration from the provided config and provides helpers to build OAuth URLs and start a login (full-page or popup). Automatically handles OAuth callbacks by detecting code and state URL parameters and exchanging them for a session — and, when the callback is running inside a popup we opened, relaying the result to the opener instead.

function useOAuth(config?: {
  baseURL?: string
  oauthProviders?: string[]
  oauthEndpoint?: string
  loginEndpoint?: string
  onSuccess?: () => void
  onError?: (error: string) => void
}): UseOAuthReturn
  • config — Optional OAuth configuration override.
  • config.baseURL — Base URL for the API server (e.g. "https://api.example.com").
  • config.oauthProviders — List of supported OAuth provider names (e.g. ["google", "github"]).
  • config.oauthEndpoint — Path prefix for OAuth routes (defaults to "/oauth").
  • config.loginEndpoint — Path for the OAuth login POST endpoint (defaults to "/users/log-in/oauth").
  • config.onSuccess — Callback after successful OAuth login.
  • config.onError — Callback on OAuth login failure.

Returns: OAuth helpers: providers, getOAuthUrl, redirect, and loginViaPopup.

usePasswordReset()

Hook for password reset flow with async state tracking.

Provides separate tracking for the request and confirm steps.

function usePasswordReset(): UsePasswordResetReturn

Returns: Password reset state and actions

usePlatform()

Hook for platform detection.

Uses module-level functions — platform is a singleton, not context-provided. Platform info is static and doesn't change at runtime, so this uses useMemo.

function usePlatform(): UsePlatformResult

Returns: Platform information and utility methods

usePreviewProvider()

Access the preview provider from context.

function usePreviewProvider(): PreviewProvider

Returns: The PreviewProvider instance from the nearest PreviewContext.

usePreview()

Hook for live preview management.

function usePreview(): UsePreviewResult

Returns: Preview state and controls: state (url, isLoading, device, error, isConnected), setUrl, refresh, setDevice, and openExternal.

usePush(options)

Hook for push notification state and actions.

Uses module-level getProvider() — push is a singleton, not context-provided.

function usePush(options?: UsePushOptions): UsePushResult
  • options — Hook options

Returns: Push notification state and action methods

useRouterInstance()

Hook to access the router from context.

function useRouterInstance(): Router

Returns: The router from context

useRouter()

Hook for routing state and actions.

function useRouter(): UseRouterResult

Returns: Router state and navigation methods

useLocation()

Hook to get the current location.

function useLocation(): RouteLocation

Returns: The current route location

useParams()

Hook to get route parameters.

function useParams(): T

Returns: The current route parameters

useQuery()

Hook to get query parameters.

function useQuery(): T

Returns: The current query parameters

useNavigate()

Hook to get the navigate function.

function useNavigate(): (path: string, options?: NavigateOptions) => void

Returns: The navigate function

useIsActive(path, exact)

Hook to check if a path is active.

function useIsActive(path: string, exact?: boolean): boolean
  • path — The path to check
  • exact — Whether to match exactly (default: false)

Returns: Whether the path is active

useSignup()

Hook for user registration with async state tracking.

function useSignup(): UseSignupReturn<T>

Returns: Signup state and action

useStorageProvider()

Hook to access the storage provider from context.

function useStorageProvider(): StorageProvider

Returns: The storage provider from context

useStorageValue(key, options)

Hook to manage a single storage value with React state sync.

function useStorageValue(key: string, options?: UseStorageValueOptions<T>): UseStorageValueResult<T>
  • key — Storage key
  • options — Hook options

Returns: Storage value state (value, loading, error) and mutators (setValue, removeValue).

useStorage()

Hook for simple storage operations without React state sync.

function useStorage(): {
  get: <T>(key: string) => Promise<T | null>
  set: <T>(key: string, value: T) => Promise<void>
  remove: (key: string) => Promise<void>
  clear: () => Promise<void>
  keys: () => Promise<string[]>
}

Returns: Storage operation methods

useStateProvider()

Hook to access the state provider from context.

The context comes from <StateProvider provider={…}> or from <MoleculeProvider> — which supplies the provider bonded under @molecule/app-state by default, so a scaffolded app needs no state prop.

Only hooks that read the context call this; useStore(store) takes its store as an argument and works with no provider at all.

function useStateProvider(): StateProvider

Returns: The state provider from context

useStore(store, options)

Hook to subscribe to a store with optional selector and equality function.

The store is the argument, so this hook needs NO StateProvider: it reads store.getState() and subscribes with store.subscribe(), and never touches the state context. A store minted outside the state bond — the direct createStoreWithActions() / createStore() a provider package exports — is therefore as valid here as one @molecule/app-state's createStore() made.

function useStore(store: Store<T>, options?: UseStoreOptions<T, S>): S
  • store — The store to subscribe to
  • options — Hook options (selector, equalityFn)

Returns: The selected state

useSetStore(store)

Hook to get the store's setState function.

function useSetStore(store: Store<T>): (partial: Partial<T> | ((state: T) => Partial<T>)) => void
  • store — The store to get setState from

Returns: The setState function

useStoreAction(store, action)

Hook to create a bound action for a store.

function useStoreAction(
  store: Store<T>,
  action: (setState: Store<T>['setState'], getState: Store<T>['getState']) => (...args: Args) => R,
): (...args: Args) => R
  • store — The store to bind to
  • action — The action function that receives setState and getState

Returns: A bound action function

useThemeProvider()

Hook to access the theme provider from context.

function useThemeProvider(): ThemeProvider

Returns: The theme provider from context

useTheme()

Hook for theme state and actions.

function useTheme(): UseThemeResult

Returns: Theme state and actions

useCurrentTheme()

Hook to get just the current theme object.

function useCurrentTheme(): Theme

Returns: The current theme

useThemeMode()

Hook to get just the theme mode (light/dark).

function useThemeMode(): 'light' | 'dark'

Returns: The current theme mode

useThemeColors()

Hook to get theme colors.

function useThemeColors(): ThemeColors

Returns: The current theme colors

useI18nProvider()

Hook to access the i18n provider from context.

function useI18nProvider(): I18nProvider

Returns: The i18n provider from context

useTranslation()

Hook for internationalization.

function useTranslation(): UseTranslationResult

Returns: Translation function and locale management

useT()

Hook to get just the translation function.

function useT(): (
  key: string,
  values?: InterpolationValues,
  options?: { defaultValue?: string; count?: number },
) => string

Returns: The translation function

useLocale()

Hook to get the current locale.

function useLocale(): string

Returns: The current locale code

useDirection()

Hook to get the text direction.

function useDirection(): 'ltr' | 'rtl'

Returns: The text direction ('ltr' or 'rtl')

useI18nError(error)

Translates an error at render time so the displayed message updates automatically when the locale changes.

Always use this hook to display errors in React components — accessing error.message directly bypasses re-translation and leaves stale text after a locale switch. If error is an I18nError (thrown via throw new I18nError(key)), its key is translated using the current locale. For plain Error instances, error.message is returned unchanged.

function useI18nError(error: Error | null | undefined): string | null
  • error — The error to translate, or null/undefined.

Returns: The translated error string, or null if no error.

useVerifyPaymentReturn(options)

Reads the payment id a provider put in the return URL and confirms the purchase server-side with POST /users/:id/verify-payment/:provider.

This is why a hosted checkout returns the buyer to the APP and not the API. Session cookies are host-only on the app's origin, so a top-level redirect from the provider straight to an authenticated API callback on a different host arrives with NO credentials — it answers 401 and the paid plan is never granted. The request this hook makes is a same-origin call from a loaded app page, so the credentials apply. It waits for auth to hydrate first: after the redirect the page is a cold load, and the session is restored from the httpOnly cookie via GET /users/me.

Verification is idempotent server-side (first-claim-wins on the transaction), and this hook additionally runs at most once per transaction id per page. Safe on pages that are also reached normally: with no id in the URL it stays idle and issues no request.

function useVerifyPaymentReturn(
  options?: UseVerifyPaymentReturnOptions,
): UseVerifyPaymentReturnResult
  • options — Provider fallback + lifecycle callbacks (see UseVerifyPaymentReturnOptions).

Returns: The verification state (see UseVerifyPaymentReturnResult).

useVersion()

Hook for version state and update actions.

Uses module-level getProvider() — version is a singleton, not context-provided.

function useVersion(): UseVersionResult

Returns: Version state and action methods

useWorkspaceProvider()

Access the workspace provider from context.

function useWorkspaceProvider(): WorkspaceProvider

Returns: The result.

useWorkspace()

Hook for IDE workspace layout management.

function useWorkspace(): UseWorkspaceResult

Returns: The workspace state and management methods.

StateProvider(props)

Provider for state management.

function StateProvider({
  provider,
  children,
}: StateProviderProps): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>
  • props — Component props (see StateProviderProps).

Returns: The rendered state provider element.

AuthProvider(props)

Provider for authentication.

function AuthProvider({
  client,
  children,
}: AuthProviderProps<T>): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>
  • props — Component props (see AuthProviderProps).

Returns: The rendered auth provider element.

ThemeProvider(props)

Provider for theming.

function ThemeProvider({
  provider,
  children,
}: ThemeProviderProps): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>
  • props — Component props (see ThemeProviderProps).

Returns: The rendered theme provider element.

RouterProvider(props)

Provider for routing.

function RouterProvider({
  router,
  children,
}: RouterProviderProps): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>
  • props — Component props (see RouterProviderProps).

Returns: The rendered router provider element.

I18nProvider(props)

Provider for internationalization.

function I18nProvider({
  provider,
  children,
}: I18nProviderProps): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>
  • props — Component props (see I18nProviderProps).

Returns: The rendered i18n provider element.

HttpProvider(props)

Provider for HTTP client.

function HttpProvider({
  client,
  children,
}: HttpProviderProps): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>
  • props — Component props (see HttpProviderProps).

Returns: The rendered HTTP provider element.

StorageProvider(props)

Provider for storage.

function StorageProvider({
  provider,
  children,
}: StorageProviderProps): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>
  • props — Component props (see StorageProviderProps).

Returns: The rendered storage provider element.

LoggerProvider(props)

Provider for logging.

function LoggerProvider({
  provider,
  children,
}: LoggerProviderProps): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>
  • props — Component props (see LoggerProviderProps).

Returns: The rendered logger provider element.

ChatProvider(props)

Provider for AI chat.

function ChatProvider({
  provider,
  children,
}: ChatProviderProps): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>
  • props — Component props (see ChatProviderProps).

Returns: The rendered chat provider element.

WorkspaceProvider(props)

Provider for IDE workspace.

function WorkspaceProvider({
  provider,
  children,
}: WorkspaceProviderProps): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>
  • props — Component props (see WorkspaceProviderProps).

Returns: The rendered workspace provider element.

EditorProvider(props)

Provider for code editor.

function EditorProvider({
  provider,
  children,
}: EditorProviderProps): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>
  • props — Component props (see EditorProviderProps).

Returns: The rendered editor provider element.

PreviewProvider(props)

Provider for live preview.

function PreviewProvider({
  provider,
  children,
}: PreviewProviderProps): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>
  • props — Component props (see PreviewProviderProps).

Returns: The rendered preview provider element.

MoleculeProvider(props)

Combined provider for all molecule services.

Provides a convenient way to wrap your app with all molecule providers at once. Only providers that are passed will be included — except state, which falls back to the state provider bonded under @molecule/app-state (set by setupAllDefaultBonds() or a state bond) so useStore() works without a state prop.

function MoleculeProvider({
  children,
  state,
  auth,
  theme,
  router,
  i18n,
  http,
  storage,
  logger,
  chat,
  workspace,
  editor,
  preview,
}: MoleculeProviderProps): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>
  • props — Component props (see MoleculeProviderProps) — each service is optional, and ONLY the services passed are provided to the tree.

Returns: The rendered combined provider element.

Constants

DEFAULT_AGENT_NAME

Neutral, product-agnostic agent name used when the host supplies none.

const DEFAULT_AGENT_NAME: 'the assistant'

DEFAULT_PRODUCT_NAME

Neutral, product-agnostic product/IDE name used when the host supplies none.

const DEFAULT_PRODUCT_NAME: 'the IDE'

DEFAULT_AGENT_IDENTITY

The neutral default identity (DEFAULT_AGENT_NAME + DEFAULT_PRODUCT_NAME) the shared packages use until a consuming app passes its own.

const DEFAULT_AGENT_IDENTITY: AgentIdentity

StateContext

Context for state management provider.

const StateContext: Context<StateProvider | null>

AuthContext

Context for authentication client.

const AuthContext: Context<AuthClient<unknown> | null>

ThemeContext

Context for theme provider.

const ThemeContext: Context<ThemeProvider | null>

RouterContext

Context for router.

const RouterContext: Context<Router | null>

I18nContext

Context for internationalization provider.

const I18nContext: Context<I18nProvider | null>

HttpContext

Context for HTTP client.

const HttpContext: Context<HttpClient | null>

StorageContext

Context for storage provider.

const StorageContext: Context<StorageProvider | null>

LoggerContext

Context for logger provider.

const LoggerContext: Context<LoggerProvider | null>

ChatContext

Context for AI chat provider.

const ChatContext: Context<ChatProvider | null>

WorkspaceContext

Context for IDE workspace provider.

const WorkspaceContext: Context<WorkspaceProvider | null>

EditorContext

Context for code editor provider.

const EditorContext: Context<EditorProvider | null>

PreviewContext

Context for live preview provider.

const PreviewContext: Context<PreviewProvider | null>

useAsyncState

Hook like useState but accepts Promises and supports partial state extension.

const useAsyncState: <T>(initialState: T) => [T, AsyncSetState<T>, AsyncExtendState<T>]
  • initialState — Initial state value

Returns: Tuple of [state, asyncSetState, asyncExtendState]

usePromise

Hook that wraps an async function with state tracking.

const usePromise: <T extends (...args: any[]) => Promise<any>>(
  asyncFn: T,
) => [
  UsePromiseState<Awaited<ReturnType<T>>>,
  (...args: Parameters<T>) => Promise<Awaited<ReturnType<T>>>,
]
  • asyncFn — The async function to wrap

Returns: Tuple of [state, wrappedFunction]

Injection Notes

Requirements

Peer dependencies:

  • @molecule/app-keyboard ^1.0.1
  • @molecule/app-lifecycle ^1.0.1
  • @molecule/app-react ^1.0.1
  • react ^18.0.0 || ^19.0.0
  • react-native >=0.72.0
  • react-native-safe-area-context >=4.0.0

Runtime Dependencies

  • @molecule/app-keyboard

  • @molecule/app-lifecycle

  • @molecule/app-react

  • react

  • react-native

  • react-native-safe-area-context

  • The re-exported hooks keep @molecule/app-react's contract: each one throws unless its provider was passed to MoleculeProvider (or mounted individually). See the @molecule/app-react docs for the hook→provider map.

  • useSafeArea needs SafeAreaProvider (from react-native-safe-area-context) mounted at the root; without it — or without the library installed — it silently returns zero insets rather than throwing, so a notch-overlapped header means missing provider, not a bug in the hook.

  • useBackHandler only fires on Android; iOS has no hardware back button.

  • For components/styling pair this with @molecule/app-ui-react-native, whose ClassMap styling requires the NativeWind setup (@molecule/app-ui-nativewind) — see that package's docs.