Appearance
Usage
Apollo client setup
Install Apollo if your app does not already use it:
sh
yarn add @apollo/client graphqlInitialize the client with the device identifier in the headers and wrap your app with ApolloProvider:
tsx
import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client'
import { ApolloProvider } from '@apollo/client/react'
import { deviceIdentifier } from 'trainingkit-reactnative'
const client = new ApolloClient({
link: new HttpLink({
uri: 'https://your-graphql-endpoint/graphql',
headers: {
'X-TrainingKit-Device': deviceIdentifier(),
},
}),
cache: new InMemoryCache(),
})
export function App() {
return (
<ApolloProvider client={client}>
{/* Your navigation tree */}
</ApolloProvider>
)
}The two-step flow
Launching a workout always takes two GraphQL calls:
- List query — returns lightweight workout previews (
id,name,format, …) to display a catalog. It does not includetrainingKitToken. - Session content query — fetches the full session payload for one workout by
id, includingtrainingKitToken. This is the object you pass tolaunchWorkout.
Fetch the full session lazily, only when the user selects a workout, so you do not request a launch token for every item in the list.
Listing workouts
The GraphQL documents depend on your generated schema. The list query should return workout preview items that include at minimum: id, name, duration, picture, and format.
format values are CLASSIC (classic guided workout) and PLAY (video workout). In the demo's generated types these map to the WorkoutFormat.Classic and WorkoutFormat.Play enum members used below.
tsx
import { useQuery } from '@apollo/client/react'
import { Pressable, SectionList, Text } from 'react-native'
import { GetSessionsDocument, WorkoutFormat } from '../graphql/types'
export function SessionsScreen({ onSelect }: { onSelect: (id: string) => void }) {
const { data, loading, error } = useQuery(GetSessionsDocument)
if (loading) return <Text>Loading...</Text>
if (error) return <Text>{error.message}</Text>
const sections = [
{
title: 'Classic workouts',
data: data?.publicWorkouts.edges
.filter(edge => edge.node.format === WorkoutFormat.Classic)
.map(edge => edge.node) ?? [],
},
{
title: 'Video workouts',
data: data?.publicWorkouts.edges
.filter(edge => edge.node.format === WorkoutFormat.Play)
.map(edge => edge.node) ?? [],
},
]
return (
<SectionList
sections={sections}
keyExtractor={item => item.id}
renderSectionHeader={({ section }) => <Text>{section.title}</Text>}
renderItem={({ item }) => (
<Pressable onPress={() => onSelect(item.id)}>
<Text>{item.name}</Text>
</Pressable>
)}
/>
)
}Launching a workout
To launch a workout, fetch the full session payload first. The full session response must include trainingKitToken.
tsx
import { useLazyQuery } from '@apollo/client/react'
import { Alert } from 'react-native'
import { launchWorkout } from 'trainingkit-reactnative'
import { GetSessionContentDocument } from '../graphql/types'
export function useWorkoutLauncher() {
const [fetchSessionContent] = useLazyQuery(GetSessionContentDocument)
return async function launchWorkoutById(id: string) {
try {
const { data } = await fetchSessionContent({ variables: { id } })
const session = data?.publicWorkoutSession
if (!session) {
throw new Error('Workout session not found')
}
launchWorkout(session)
} catch (error) {
Alert.alert(
'Workout error',
error instanceof Error ? error.message : String(error),
)
}
}
}launchWorkout determines the workout kind from the session and dispatches to the correct native SDK:
__typename === 'WorkoutBlockSession'orformat === 'CLASSIC'→ classic workout__typename === 'WorkoutVideoSession'orformat === 'PLAY'→ video workout
If neither condition matches, launchWorkout throws with the unrecognized type.
GraphQL contract
The package does not own the Apollo client or the GraphQL schema. Your application is responsible for:
- Sending
X-TrainingKit-Devicewith every request (see Authentication). - Querying the workout list and retrieving a preview item.
- Fetching the full session payload (including
trainingKitToken) before callinglaunchWorkout.
The session object passed to launchWorkout must conform to:
ts
type TrainingKitSession = {
__typename?: string
format?: string
trainingKitToken: string
[key: string]: unknown
}Any additional fields from the GraphQL response are preserved and forwarded to the native SDK as part of the JSON payload.
