Overview
Use timeback.user.fetch() to retrieve the enriched Timeback profile for the current user, including:
- Identity information
- School and grade
- Enrolled courses
- Goals and progress
- XP totals
Server-Side Usage
const profile = await timeback.user.fetch()
console.log(profile.school?.name)
console.log(profile.xp?.today, profile.xp?.all)
Profile Shape
interface UserProfile {
id: string
email: string
name?: string
school?: {
id: string
name: string
}
grade?: number
courses: Course[]
goals: Goal[]
xp: {
today: number // XP earned today (UTC)
all: number // Total XP (since 2000-01-01)
}
}
Client-Side Hooks
import { useTimebackProfile } from '@timeback/sdk/react'
// Manual fetch
function ProfileButton() {
const { state, canFetch, fetchProfile } = useTimebackProfile()
if (state.status === 'loaded') {
return <div>XP: {state.profile.xp.today}</div>
}
return (
<button onClick={fetchProfile} disabled={!canFetch}>
{state.status === 'loading' ? 'Loading...' : 'Load Profile'}
</button>
)
}
// Auto-fetch when verified
function AutoProfile() {
const { state } = useTimebackProfile({ auto: true })
if (state.status === 'loading') return <div>Loading...</div>
if (state.status === 'loaded') return <div>XP: {state.profile.xp.today}</div>
return null
}
<script setup>
import { useTimebackProfile } from '@timeback/sdk/vue'
const { state, canFetch, fetchProfile } = useTimebackProfile()
</script>
<template>
<div v-if="state.status === 'loaded'">
XP: {{ state.profile.xp.today }}
</div>
<button v-else @click="fetchProfile" :disabled="!canFetch">
{{ state.status === 'loading' ? 'Loading...' : 'Load Profile' }}
</button>
</template>
<script>
import {
timebackProfile,
timebackProfileCanFetch,
fetchTimebackProfile
} from '@timeback/sdk/svelte'
</script>
<button onclick={fetchTimebackProfile} disabled={!$timebackProfileCanFetch}>
{$timebackProfile.status === 'loading' ? 'Loading...' : 'Load Profile'}
</button>
{#if $timebackProfile.status === 'loaded'}
<div>XP: {$timebackProfile.profile.xp.today}</div>
{/if}
import { createTimebackProfile } from '@timeback/sdk/solid'
import { Show } from 'solid-js'
function ProfileButton() {
const { state, canFetch, fetchProfile } = createTimebackProfile()
return (
<Show
when={state.status === 'loaded'}
fallback={
<button onClick={fetchProfile} disabled={!canFetch}>
{state.status === 'loading' ? 'Loading...' : 'Load Profile'}
</button>
}
>
<div>XP: {state.profile.xp.today}</div>
</Show>
)
}
Profile State
The profile hook returns a state object with these statuses:
| Status | Description |
|---|
idle | Initial state, no fetch attempted |
loading | Fetch in progress |
loaded | Profile successfully loaded |
error | Fetch failed |
type ProfileState =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'loaded'; profile: UserProfile }
| { status: 'error'; error: Error }
XP Calculation
The profile.xp field contains:
XP earned during the current UTC day
Total XP over all time (since 2000-01-01)
XP is calculated from Caliper events sent during activity tracking.
Caching
The SDK caches profile data to minimize API calls:
- Profile is fetched once per session
- Manual refetch available via
fetchProfile()
- Cache is invalidated on sign-out
Next Steps