Skip to main content

App shell and providers

The native package does not export a catch-all Provider. The canonical application shell uses OvokProvider from @ovok/core and the UI ThemeProvider from @ovok/native.

The example app's provider order is:

  1. KeyboardProvider
  2. OvokProvider
  3. ThemeProvider from @ovok/native
  4. BottomSheetModalProvider
  5. Ovok's re-exported BottomSheetModalProvider for SDK sheets
  6. Navigation's theme provider
  7. Your navigation and screens

The two bottom-sheet providers are intentionally distinct. The inner @ovok/native provider is required by SDK components that use the SDK's sheet implementation.

Minimal root layout​

import { OvokClient, OvokProvider } from "@ovok/core";
import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";
import { DefaultTheme, ThemeProvider } from "@react-navigation/native";
import {
BottomSheetModalProvider as OvokBottomSheetModalProvider,
DEFAULT_COLORS,
DEFAULT_MULTIPLIERS,
ExpoClientStorage,
ThemeProvider as OvokThemeProvider,
polyfillMedplumWebAPIs,
} from "@ovok/native";
import { Stack } from "expo-router";
import { KeyboardProvider } from "react-native-keyboard-controller";

polyfillMedplumWebAPIs();

const client = new OvokClient({
storage: new ExpoClientStorage(),
baseUrl: "https://api.ovok.com",
fhirUrlPath: "/fhir",
socialLoginClientId: process.env.EXPO_PUBLIC_OVOK_CLIENT_ID,
});

export default function RootLayout() {
return (
<KeyboardProvider>
<OvokProvider client={client}>
<OvokThemeProvider
theme={{
colors: DEFAULT_COLORS,
dark: false,
spacingMultiplier: DEFAULT_MULTIPLIERS.spacing,
borderRadiusMultiplier: DEFAULT_MULTIPLIERS.borderRadius,
}}
>
<BottomSheetModalProvider>
<OvokBottomSheetModalProvider>
<ThemeProvider value={DefaultTheme}>
<Stack />
</ThemeProvider>
</OvokBottomSheetModalProvider>
</BottomSheetModalProvider>
</OvokThemeProvider>
</OvokProvider>
</KeyboardProvider>
);
}

Use your app's environment system for URLs and client IDs. Never commit production credentials or copy the example app's values.

Theme contract​

ThemeProvider accepts a theme with:

  • colors, usually based on DEFAULT_COLORS;
  • dark, the current color mode;
  • spacingMultiplier, normally DEFAULT_MULTIPLIERS.spacing;
  • borderRadiusMultiplier, normally DEFAULT_MULTIPLIERS.borderRadius.

Components read the resulting theme through useAppTheme(). Navigation has its own theme contract, so merge the same brand colors into the navigation theme separately.

Context requirement​

The following features expect to be rendered below OvokProvider:

  • auth forms and logout/account controls;
  • patient and observation components that use the active profile;
  • DataSync components;
  • SocketProvider and socket hooks;
  • questionnaire form submission helpers;
  • Bluetooth result handlers that persist through the app's core client.

If a component renders but has no data, first verify provider order and the active patient/login state before changing component props.