React Native / Expo
@noryen/sdk is plain TypeScript with no native modules—it runs in React Native and Expo the same as in Node, as long as you have fetch (Hermes / modern RN do).
Install
npm install @noryen/sdk (or yarn / pnpm) in your app package.
API key in the client
Expo public env vars (for example EXPO_PUBLIC_NORYEN_API_KEY) are bundled into the app—anyone with the binary can extract them. Prefer a backend or Edge function that holds NORYEN_API_KEY if you need strict secrecy; use the client-only flow below when you accept that tradeoff (similar to other client analytics keys).
Initialize once
// lib/noryen.tsimport { noryen } from "@noryen/sdk";let initialized = false;export function ensureNoryenInitialized() {if (initialized) {return;}const apiKey = process.env.EXPO_PUBLIC_NORYEN_API_KEY;if (!apiKey) {initialized = true;return;}noryen.init({ apiKey, debug: __DEV__ });initialized = true;}ensureNoryenInitialized();export { noryen };
Import the module from your root layout so initialization runs at app startup:
// app/_layout.tsximport "@/lib/noryen";// …rest of layout (providers, fonts, etc.)
Global metadata
Use noryen.setContext() for fields you want on every trace (platform, app version, environment):
// providers/app-context.tsx (example)import { useEffect } from "react";import { Platform } from "react-native";import Constants from "expo-constants";import { noryen } from "@/lib/noryen";export function NoryenAppContext() {useEffect(() => {noryen.setContext({platform: Platform.OS,appVersion: Constants.expoConfig?.version,});}, []);return null;}
Manual track()
If you call OpenRouter or another HTTP API yourself, emit traces with noryen.track(). Attach TrackContext when you have documents or retrieval data to record:
import { noryen } from "@/lib/noryen";const model = "google/gemini-2.0-flash-001";async function generatePlan(prompt: string, inputData: string) {const started = Date.now();try {const result = await callOpenRouter(prompt);noryen.track({model,provider: "openrouter",success: true,prompt,response: result,latency: Date.now() - started,metadata: { feature: "personal_plan_generation" },context: {documents: [{ content: inputData, source: "app.health_data" }],retrieval: { query: "user health data", method: "manual", k: 1 },},});return result;} catch (err) {noryen.track({model,provider: "openrouter",success: false,error: err instanceof Error ? err.message : String(err),prompt,response: "",latency: Date.now() - started,});throw err;}}
context (documents, retrieval, instructions) see TrackContext.