Skip to main content

Quick start

This guide connects an Expo Router app to an OVOK environment and renders a working email sign-in screen. It assumes you have an OVOK API URL and a patient tenant code. If you are choosing native dependencies or configuring platform permissions, start with Installation and native setup.

The repository example currently uses Expo SDK 57 and React Native 0.86.3. Match the versions and peer dependencies to your app; the installation guide is the source for this repository's compatibility baseline. The complete SDK needs a native build. Expo Go does not include all of its native modules.

1. Install the SDK​

npm install @ovok/native @ovok/core

Install the peer dependencies required by the APIs you will import. Use the peer-dependency matrix in Installation and native setup, and use npx expo install for Expo packages so Expo can select compatible versions. The code below uses the SDK root entry, theme, and authentication UI. For a smaller import surface, use the documented subpaths in the Public API map.

2. Add your OVOK environment values​

Create .env.local in the Expo app root and replace the sample values with the ones for your OVOK environment:

EXPO_PUBLIC_OVOK_BASE_URL=https://api.example.com
EXPO_PUBLIC_TENANT_CODE=your-patient-tenant-code

Expo embeds EXPO_PUBLIC_ values in the app bundle. Use them for public configuration only; never put private credentials or secrets in them. Restart Expo after changing the file.

3. Initialize the app shell​

First initialize the runtime from the entry module as shown in Polyfills and runtime setup. The client example below assumes that bootstrap completed before this app module was loaded. In an Expo Router app, put the following in app/_layout.tsx; if your project uses Expo's src directory, use src/app/_layout.tsx instead.

import { OvokClient, OvokProvider } from "@ovok/core";
import {
DEFAULT_COLORS,
DEFAULT_MULTIPLIERS,
ExpoClientStorage,
ThemeProvider as OvokThemeProvider,
} from "@ovok/native";
import { Stack } from "expo-router";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { KeyboardProvider } from "react-native-keyboard-controller";

const baseUrl = process.env.EXPO_PUBLIC_OVOK_BASE_URL;

if (!baseUrl) {
throw new Error("Set EXPO_PUBLIC_OVOK_BASE_URL in .env.local");
}

// Keep the client outside the component so it is not recreated on each render.
const client = new OvokClient({
storage: new ExpoClientStorage(),
baseUrl,
fhirUrlPath: "/fhir",
});

export default function RootLayout() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<KeyboardProvider>
<OvokProvider client={client}>
<OvokThemeProvider
theme={{
colors: DEFAULT_COLORS,
dark: false,
spacingMultiplier: DEFAULT_MULTIPLIERS.spacing,
borderRadiusMultiplier: DEFAULT_MULTIPLIERS.borderRadius,
}}
>
<Stack />
</OvokThemeProvider>
</OvokProvider>
</KeyboardProvider>
</GestureHandlerRootView>
);
}

KeyboardProvider supports the keyboard-aware sign-in form. Add BottomSheetModalProvider and a navigation theme when the screens you use need them; see App shell and providers for the full provider setup.

4. Add the sign-in route​

Create app/index.tsx (or src/app/index.tsx) and add the email sign-in screen. Patient sign-in requires a tenant code; SignIn.EmailForm reports success and errors so your app can own navigation and messaging.

import { SignIn } from "@ovok/native";
import { useRouter } from "expo-router";
import { Alert } from "react-native";

const tenantCode = process.env.EXPO_PUBLIC_TENANT_CODE;

if (!tenantCode) {
throw new Error("Set EXPO_PUBLIC_TENANT_CODE in .env.local");
}

export default function SignInScreen() {
const router = useRouter();

return (
<SignIn>
<SignIn.Header>
<SignIn.Header.Title />
</SignIn.Header>

<SignIn.EmailForm
loginType="Patient"
tenantCode={tenantCode}
onSuccess={() => router.replace("/home")}
onError={(error) => Alert.alert("Sign-in failed", error.message)}
>
<SignIn.EmailForm.Inputs />
<SignIn.EmailForm.SigninButton />
</SignIn.EmailForm>
</SignIn>
);
}

5. Add a destination after sign-in​

Create app/home.tsx (or src/app/home.tsx) so the success route exists:

import { Text, View } from "react-native";

export default function HomeScreen() {
return (
<View
style={{
flex: 1,
alignItems: "center",
justifyContent: "center",
}}
>
<Text>You are signed in.</Text>
</View>
);
}

Replace this screen and the /home route with your app's authenticated navigation when you integrate the flow. For MFA and social sign-in setup, continue to Authentication.

6. Build and run on a native target​

Build and launch on an iOS simulator/device:

npx expo prebuild
npx expo run:ios

Or build and launch on Android:

npx expo prebuild
npx expo run:android

prebuild applies your Expo config and native plugins. Rebuild the native app after adding a native dependency or changing a config plugin. JavaScript-only changes do not require another prebuild. See Troubleshooting if the native build or sign-in flow fails.

Where to go next​