Documentation Index Fetch the complete documentation index at: https://docs.timeback.com/llms.txt
Use this file to discover all available pages before exploring further.
Templates and example integrations help you move faster and avoid rework. Use these as starting points for your integration.
Starter Templates
Template Framework Description nextjs-app-routerNext.js App Router with SSO and activity tracking nuxtNuxt 3 Server middleware with Vue composables svelte-kitSvelteKit Hooks-based integration with stores solid-startSolidStart Middleware with primitives tanstack-startTanStack Start File-based routes with React expressExpress Standalone API server express-auth0Express + Auth0 Custom auth mode with Auth0 express-supabaseExpress + Supabase Custom auth mode with Supabase bun-reactBun + React Minimal SSO example bun-react-identity-onlyBun + React Identity-only mode (no activity tracking)
All templates are available in the examples directory .
bun-react
SSO authentication and activity tracking with Bun server and React frontend.
This example shows the SDK handlers (/api/timeback/*) plus a simple UI.
For an example that also demonstrates the direct API escape hatch (timeback.api),
see examples/bun-react-full.
Quick Start
cp .env.example .env
# Add your TIMEBACK_SSO_CLIENT_ID and TIMEBACK_SSO_CLIENT_SECRET
bun install
bun dev
Structure
File Purpose src/index.tsBun server + Timeback routes src/lib/timeback.tsSSO config + session management src/App.tsxSignInButton + activity demo src/frontend.tsxReact entry point
Key Patterns
Native handler — Mount Timeback routes:
// index.ts
import { timebackHandler } from './lib/timeback'
if ( url . pathname . startsWith ( '/api/timeback' )) {
return timebackHandler ( request )
}
SignInButton — Pre-styled SSO button:
import { SignInButton } from '@timeback/sdk/react'
; < SignInButton />
Activity tracking — Track learning time:
import { useTimeback } from '@timeback/sdk/react'
const timeback = useTimeback ()
const activity = timeback . activity . start ({
id: 'lesson_1' ,
name: 'Fractions' ,
course: { subject: 'FastMath' , grade: 3 }, // must match timeback.config.json
})
< p > Time: { activity . totalActiveMs } ms </ p >
bun-react-full
SSO authentication and activity tracking with Bun server and React frontend.
This “full” variant also includes a small demo of direct API access via timeback.api
(an escape hatch for calling Timeback services like OneRoster).
Quick Start
cp .env.example .env
# Add your TIMEBACK_SSO_CLIENT_ID and TIMEBACK_SSO_CLIENT_SECRET
bun install
bun dev
Structure
File Purpose src/index.tsBun server + Timeback routes src/lib/timeback.tsSSO config + session management src/App.tsxSignInButton + activity demo src/frontend.tsxReact entry point
Key Patterns
Native handler — Mount Timeback routes:
// index.ts
import { timebackHandler } from './lib/timeback'
if ( url . pathname . startsWith ( '/api/timeback' )) {
return timebackHandler ( request )
}
SignInButton — Pre-styled SSO button:
import { SignInButton } from '@timeback/sdk/react'
; < SignInButton />
Activity tracking — Track learning time:
import { useActivity } from '@timeback/sdk/react'
const activity = useActivity ({
id: 'lesson_1' ,
name: 'Fractions' ,
course: { subject: 'FastMath' , grade: 3 } // must match a unique course in timeback.config.json
})
< p > Time: { activity . totalActiveMs } ms </ p >
bun-react-gradeless
SSO authentication and activity tracking for grade-less apps (e.g., CS platforms).
This example demonstrates using courseCode instead of (subject, grade) for course identity.
Quick Start
cp .env.example .env
# Add your TIMEBACK_SSO_CLIENT_ID and TIMEBACK_SSO_CLIENT_SECRET
bun install
bun dev
Grade-less Course Configuration
Apps without grade levels use courseCode as the course identifier:
// timeback.config.json
{
"$schema" : "https://timeback.dev/schema.json" ,
"name" : "CodeQuest" ,
"courses" : [
{
"subject" : "Other" ,
"courseCode" : "INTRO-CS-101" ,
"ids" : { "staging" : "..." , "production" : "..." }
},
{
"subject" : "Other" ,
"courseCode" : "DATA-STRUCTURES-201" ,
"ids" : { "staging" : "..." , "production" : "..." }
}
]
}
Activity Tracking with courseCode
When evaluating examples, it’s often useful to preview what would be sent
without actually sending Caliper events. This example uses:
normal activity.end(...) (production-like)
a server-side hook (beforeActivitySend) to optionally skip sending and log what would be sent
Demo toggle
In .env:
# 0 = preview (log would-send events, do not send)
# 1 = send for real
TIMEBACK_DEMO_SEND_ACTIVITY = 0
Compare this to grade-based apps (see examples/bun-react):
// Grade-based
course : { subject : 'Math' , grade : 3 }
Structure
File Purpose src/index.tsBun server + Timeback routes src/lib/timeback.tsSSO config + session management src/App.tsxSignInButton + activity demo timeback.config.jsonGrade-less course configuration
bun-react-identity-only
SSO authentication with Bun server and React frontend — no activity tracking .
This example demonstrates createTimebackIdentity() for apps that only need Timeback SSO without the full SDK.
Quick Start
cp .env.example .env
# Add your TIMEBACK_SSO_CLIENT_ID and TIMEBACK_SSO_CLIENT_SECRET
bun install
bun dev
Structure
File Purpose src/index.tsBun server + Timeback routes src/lib/timeback.tsSSO config + session management src/App.tsxSignInButton + session display src/frontend.tsxReact entry point
Key Differences from Full SDK
Uses createTimebackIdentity() instead of createTimeback()
No api credentials required
No timeback.config.json required
Only identity routes are available (no activity tracking)
Key Patterns
Identity-only server — No API credentials needed:
// lib/timeback.ts
import { createTimebackIdentity } from '@timeback/sdk'
export const timeback = createTimebackIdentity ({
env: 'staging' ,
identity: {
mode: 'sso' ,
clientId: process . env . TIMEBACK_SSO_CLIENT_ID ! ,
clientSecret: process . env . TIMEBACK_SSO_CLIENT_SECRET ! ,
onCallbackSuccess : ({ user , redirect }) => {
setSession ( user )
return redirect ( '/' )
},
getUser : () => getSession (),
},
})
SignInButton — Pre-styled SSO button:
import { SignInButton } from '@timeback/sdk/react'
; < SignInButton />
bun-react-resumable
SSO authentication and activity tracking with Bun server and React frontend.
This example shows the SDK handlers (/api/timeback/*) plus a simple UI.
For an example that also demonstrates the direct API escape hatch (timeback.api),
see examples/bun-react-full.
Quick Start
cp .env.example .env
# Add your TIMEBACK_SSO_CLIENT_ID and TIMEBACK_SSO_CLIENT_SECRET
bun install
bun dev
Structure
File Purpose src/index.tsBun server + Timeback routes src/lib/timeback.tsSSO config + session management src/App.tsxSignInButton + activity demo src/frontend.tsxReact entry point
Key Patterns
Native handler — Mount Timeback routes:
// index.ts
import { timebackHandler } from './lib/timeback'
if ( url . pathname . startsWith ( '/api/timeback' )) {
return timebackHandler ( request )
}
SignInButton — Pre-styled SSO button:
import { SignInButton } from '@timeback/sdk/react'
; < SignInButton />
Activity tracking — Track learning time:
import { useTimeback } from '@timeback/sdk/react'
const timeback = useTimeback ()
const activity = timeback . activity . start ({
id: 'lesson_1' ,
name: 'Fractions' ,
course: { subject: 'FastMath' , grade: 3 }, // must match timeback.config.json
})
< p > Time: { activity . totalActiveMs } ms </ p >
express
Minimal Express.js backend demonstrating the Timeback SDK’s Express adapter.
Quick Start
Verify Routes
Run the verification script to test all routes:
This starts the server, tests all endpoints, and reports results.
Routes
Method Path Description GET /healthHealth check GET /api/timeback/identity/signinInitiate SSO sign-in GET /api/timeback/identity/callbackSSO callback handler GET /api/timeback/identity/signoutSign out POST /api/timeback/activity/heartbeatSubmit time heartbeat POST /api/timeback/activity/submitSubmit completion
Testing
# Health check
curl http://localhost:3000/health
# Submit heartbeat (requires authentication)
curl -X POST http://localhost:3000/api/timeback/activity/heartbeat \
-H "Content-Type: application/json" \
-d '{
"id": "lesson-123",
"name": "Introduction to Fractions",
"course": { "subject": "FastMath", "grade": 3 },
"runId": "11111111-1111-1111-1111-111111111111",
"startedAt": "2026-01-16T10:00:00Z",
"endedAt": "2026-01-16T10:05:00Z",
"elapsedMs": 300000,
"pausedMs": 0
}'
# Submit completion (requires authentication)
curl -X POST http://localhost:3000/api/timeback/activity/submit \
-H "Content-Type: application/json" \
-d '{
"id": "lesson-123",
"name": "Introduction to Fractions",
"course": { "subject": "FastMath", "grade": 3 },
"runId": "11111111-1111-1111-1111-111111111111",
"endedAt": "2026-01-16T10:05:00Z",
"metrics": { "totalQuestions": 10, "correctQuestions": 8, "xpEarned": 80 }
}'
Integration Options
The SDK provides two ways to integrate with Express:
Option 1: Middleware (recommended)
import { toExpressMiddleware } from '@timeback/sdk/express'
app . use ( '/api/timeback' , toExpressMiddleware ( timeback ))
Option 2: Router mounting
import { mountExpressRoutes } from '@timeback/sdk/express'
const router = express . Router ()
mountExpressRoutes ( timeback , router )
app . use ( '/api/timeback' , router )
express-auth0
Demonstrates using the Timeback SDK with Auth0 as a custom identity provider.
This example uses Auth0’s email/password authentication (Resource Owner Password Grant) with the official auth0 Node.js SDK.
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ Frontend (React) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Login Form │───▶│ POST /auth │───▶│ Session Cookie Set │ │
│ │ email/pass │ │ /login │ │ User State Updated │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ TimebackProvider + useTimeback │ │
│ │ • Activity tracking • Profile fetching │ │
│ │ • Requests include session cookie automatically │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Backend (Express) │
│ ┌─────────────────┐ ┌─────────────────────────────────────┐ │
│ │ POST /auth/login│───▶│ Auth0 SDK (passwordGrant) │ │
│ │ │ │ Validates credentials with Auth0 │ │
│ │ │◀───│ Returns user info + tokens │ │
│ │ │ └─────────────────────────────────────┘ │
│ │ Creates session │ │
│ │ cookie (JWT) │ │
│ └─────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Timeback SDK │ │
│ │ identity.mode: 'custom' │ │
│ │ getEmail: parses session cookie → returns email │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Auth0 Setup
Create an Auth0 Application
Go to Auth0 Dashboard → Applications → Create Application
Choose “Regular Web Application”
Note your Domain , Client ID , and Client Secret
Enable Password Grant
In your application settings, go to Advanced Settings → Grant Types
Enable Password grant type
Create a Database Connection (if you don’t have one)
Go to Authentication → Database → Create Connection
Enable it for your application
Create Test Users
Go to User Management → Users → Create User
Create users with email/password
Quick Start
# Install dependencies
just install
# Copy environment template
just setup
# Edit .env with your Auth0 credentials
# Then start development servers
just dev
Environment Variables
Create .env from .env.example:
# Auth0 (from your Auth0 Dashboard)
AUTH0_DOMAIN = your-tenant.auth0.com
AUTH0_CLIENT_ID = your-client-id
AUTH0_CLIENT_SECRET = your-client-secret
# Session secret (generate with: openssl rand -base64 32)
SESSION_SECRET = your-random-secret
# Timeback API (from Timeback Dashboard)
TIMEBACK_API_CLIENT_ID = your-timeback-client-id
TIMEBACK_API_CLIENT_SECRET = your-timeback-client-secret
How It Works
1. User Login
User submits email/password → Backend calls Auth0’s password grant → Auth0 validates → Returns user info → Backend creates signed JWT session cookie.
2. Session Management
The session cookie contains { sub, email, name } signed with HS256. It’s httpOnly, secure in production, and lasts 7 days.
3. Timeback Integration
// backend/src/lib/timeback.ts
export const timeback = await createTimeback ({
identity: {
mode: 'custom' ,
getEmail : async req => {
const session = await getSessionFromCookieHeader ( req . headers . get ( 'cookie' ))
return session ?. email
},
},
// ...
})
The SDK calls getEmail(req) on each request. We parse the cookie header, verify the JWT, and return the user’s email. The SDK then resolves the Timeback user by email.
4. Frontend Activity Tracking
const timeback = useTimeback ()
// Start tracking
const activity = timeback . activity . start ({ id: 'lesson_1' , name: 'Intro to Fractions' })
// End with results
await activity . end ({ xpEarned: 100 , correctQuestions: 8 , totalQuestions: 10 })
Project Structure
express-auth0/
├── backend/
│ ├── src/
│ │ ├── index.ts # Express server & routes
│ │ └── lib/
│ │ ├── auth0.ts # Auth0 SDK wrapper
│ │ ├── session.ts # JWT session cookie helpers
│ │ └── timeback.ts # Timeback SDK instance
│ └── package.json
├── frontend/
│ ├── src/
│ │ ├── App.tsx # Main app with login form
│ │ ├── main.tsx # Entry point with TimebackProvider
│ │ └── components/
│ └── package.json
├── .env.example
├── justfile
└── README.md
API Routes
Method Route Description GET /healthHealth check POST /auth/loginLogin with email/password POST /auth/logoutClear session cookie GET /api/sessionGet current user GET /api/timeback/user/meTimeback user profile POST /api/timeback/activity/heartbeatSubmit time heartbeat POST /api/timeback/activity/submitSubmit activity completion
Troubleshooting
”Invalid email or password”
Verify the user exists in Auth0 (User Management → Users)
Check that the Password grant type is enabled
Ensure the database connection is enabled for your app
Check AUTH0_DOMAIN, AUTH0_CLIENT_ID, AUTH0_CLIENT_SECRET in .env
Domain should be just your-tenant.auth0.com (no https://)
Session not persisting
Check browser dev tools → Application → Cookies
In development, cookies work on localhost
The Vite proxy ensures same-origin for cookie handling
CORS errors
The Vite dev server proxies /auth and /api to the backend
No CORS configuration needed in development
express-auth0-launch-gate
Activity tracking demo using Auth0 Universal Login (SPA + PKCE) in the frontend and Bearer-token auth in the backend, with a launch-gated entry URL (/timeback/signin).
Architecture
┌─────────────────────────────────────────────────────────────┐
│ Frontend (React + Auth0 React SDK + @timeback/sdk) │
│ - Auth0 Universal Login (PKCE) │
│ - Activity tracking with useTimeback() │
│ - Profile viewer │
└─────────────────────────────────────────────────────────────┘
│
GET /api/user/me (Bearer)
POST /api/timeback/activity/* (Bearer)
GET /api/timeback/user/me (Bearer)
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Backend (Express + Timeback SDK) │
│ - Validates Bearer JWTs via Auth0 JWKS │
│ - Custom identity mode (SDK resolves user by email claim) │
│ - Activity tracking via Caliper │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Auth0 │ Timeback API │
│ - User authentication │ - User resolution by email │
│ - Password management │ - Activity ingestion │
└─────────────────────────────────────────────────────────────┘
How It Works
Auth0 handles authentication - Frontend uses Auth0 Universal Login (Authorization Code + PKCE)
Frontend calls backend with Bearer token - API requests include Authorization: Bearer {'<'}access_token{'>'}
Backend validates token - using Auth0 JWKS + issuer + audience
SDK uses custom identity mode - The getEmail callback reads email from the request
SDK resolves Timeback user - When submitting activity, SDK looks up the Timeback user by email
This pattern is ideal when:
You have an existing Auth0 SPA
Your backend is a resource server (Bearer JWT auth)
You want a dedicated Timeback launch URL (/timeback/signin) without a separate “Sign in with Timeback” button
Quick Start
1. Auth0 Setup
Create an API in Auth0 (Applications → APIs) and copy its Identifier (this is the audience)
Create a Single Page Application in Auth0 (Applications → Applications)
In the SPA settings, set:
Allowed Callback URLs: http://localhost:5173
Allowed Logout URLs: http://localhost:5173
Allowed Web Origins: http://localhost:5173
Ensure the Database connection is enabled for the SPA (email/password hosted by Auth0)
2. Environment Setup
cd examples/express-auth0-launch-gate
cp .env.example .env
Edit .env with your credentials.
3. Install and Run
Open http://localhost:5173
Launch-gated URL
Visit http://localhost:5173/timeback/signin to simulate the Timeback launch URL.
Commands
Command Description just installInstall backend + frontend just devStart backend + frontend just dev-backendStart backend only just dev-frontendStart frontend only just setupCopy .env.example → .env
API Endpoints
Auth Endpoints
This example uses Auth0 Universal Login (SPA + PKCE) , so there are no backend
/auth/* routes. The backend behaves like a typical resource server: it only
validates Authorization: Bearer {'<'}access_token{'>'}.
Timeback SDK Endpoints
Endpoint Method Description /api/timeback/activity/heartbeatPOST Submit time heartbeat /api/timeback/activity/submitPOST Submit activity completion /api/timeback/user/meGET Get Timeback user profile /api/timeback/user/verifyGET Verify Timeback user status
Session Endpoints
Endpoint Method Description /api/healthGET Health check /api/user/meGET Auth0 user
Project Structure
express-auth0-launch-gate/
├── backend/
│ ├── src/
│ │ ├── index.ts # Express server & routes
│ │ └── lib/
│ │ ├── auth.ts # Bearer auth middleware
│ │ └── timeback.ts # Timeback SDK instance
│ └── package.json
├── frontend/
│ └── src/
│ ├── App.tsx # React app (Auth0 + launch gate)
│ └── main.tsx # Auth0Provider + TimebackProvider
├── .env.example
├── justfile
└── README.md
express-supabase
Demonstrates using the Timeback SDK with Supabase as a custom identity provider.
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ Frontend (React) │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ Login/Signup Form → POST /auth/login or /auth/signup │ │
│ │ Activity Tracking → SDK React hooks │ │
│ └───────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Backend (Express) │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ /auth/login → Supabase signInWithPassword │ │
│ │ /auth/signup → Supabase signUp │ │
│ │ /auth/logout → Clear session │ │
│ │ /api/session → Return session user │ │
│ │ /api/timeback → Timeback SDK routes │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ Session: iron-session (encrypted cookie) │
│ │
│ Timeback SDK: │
│ identity: { mode: 'custom', getEmail: req => ... } │
└─────────────────────────────────────────────────────────────────┘
│
┌───────────────┴───────────────┐
▼ ▼
┌──────────────────────┐ ┌──────────────────────┐
│ Supabase │ │ Timeback API │
│ (Authentication) │ │ (Activity Events) │
└──────────────────────┘ └──────────────────────┘
Setup
1. Install dependencies
Edit .env with your credentials:
Supabase : Get URL and Publishable key from Supabase Dashboard > Settings > API
Timeback : Get from Timeback Dashboard
3. Create a Supabase user
In your Supabase Dashboard:
Go to Authentication > Users
Click “Add user” > “Create new user”
Enter email and password
4. Start development servers
Timeback Integration
The SDK is configured with custom identity mode, reading the user’s email from the session cookie:
// backend/src/lib/timeback.ts
export const timeback = await createTimeback ({
env: 'staging' ,
identity: {
mode: 'custom' ,
getEmail : req => getEmailFromCookieHeader ( req . headers . get ( 'cookie' )),
},
api: {
clientId: process . env . TIMEBACK_API_CLIENT_ID ,
clientSecret: process . env . TIMEBACK_API_CLIENT_SECRET ,
},
})
Available Commands
Command Description just installInstall all dependencies just setupCreate .env from template just devStart both servers just dev-backendStart backend only just dev-frontendStart frontend only
nextjs-app-router
SSO authentication and activity tracking with Next.js App Router.
Quick Start
cp .env.example .env
# Add your TIMEBACK_SSO_CLIENT_ID and TIMEBACK_SSO_CLIENT_SECRET
bun install
bun run dev
Structure
File Purpose src/app/api/timeback/[...timeback]/Timeback request handler src/app/api/auth/sso/callback/timeback/Custom OAuth callback src/lib/timeback.tsSSO config + session management src/app/page.tsxSignInButton + activity demo
Key Patterns
API routes — Handle auth routes via toNextjsHandler:
// api/timeback/[...timeback]/route.ts
import { toNextjsHandler } from '@timeback/sdk/nextjs'
import { timeback } from '@/lib/timeback'
export const { GET , POST } = toNextjsHandler ( timeback )
SignInButton — Pre-styled SSO button:
import { SignInButton } from '@timeback/sdk/react'
; < SignInButton />
Activity tracking — Track learning time:
import { useTimeback } from '@timeback/sdk/react'
function MyComponent () {
const timeback = useTimeback ()
useEffect (() => {
const activity = timeback ?. activity . start ({
id: 'lesson-1' ,
name: 'Fractions' ,
courseCode: 'MATH-101' ,
})
return () => activity ?. end ({ xpEarned: 100 })
}, [ timeback ])
}
nuxt
Look at the Nuxt documentation to learn more.
Setup
Make sure to install dependencies:
# npm
npm install
# pnpm
pnpm install
# yarn
yarn install
# bun
bun install
Development Server
Start the development server on http://localhost:3000:
# npm
npm run dev
# pnpm
pnpm dev
# yarn
yarn dev
# bun
bun run dev
Production
Build the application for production:
# npm
npm run build
# pnpm
pnpm build
# yarn
yarn build
# bun
bun run build
Locally preview production build:
# npm
npm run preview
# pnpm
pnpm preview
# yarn
yarn preview
# bun
bun run preview
Check out the deployment documentation for more information.
qti-with-powerpath
Demonstrates real PowerPath API integration for adaptive learning and standard quizzes.
This example calls the actual PowerPath API - no local simulation. The app only:
Renders questions from PowerPath
Submits answers to PowerPath
Displays results from PowerPath
Quick Start
# 1. Copy environment file and add your credentials
cp .env.example .env
# 2. Install dependencies
bun install
# 3. Run the setup script (creates courses, uploads questions, configures PowerPath)
bun run setup
# 4. Start the dev server
bun dev
Open http://localhost:5174 to take a quiz.
Two Quiz Types
Type Lesson Type Questions Pass Threshold Algorithm PowerPath 100 powerpath-10030 80% PP score Adaptive - adjusts difficulty Static Quiz quiz5 None Standard - sequential
Both use the same PowerPath API endpoints - the lessonType determines behavior.
What is PowerPath 100?
PowerPath 100 refers to the powerpath-100 lesson type that uses PowerPath’s adaptive algorithm. The “100” comes from the goal: reaching a PowerPath score of 100.
How the algorithm works:
Score starts at 0 and the goal is to reach 100
Question difficulty is selected based on current score:
0-49 : Easy questions
50-89 : Medium + Hard mix (75%/25%)
90-99 : Hard questions only
Correct answers increase your score; incorrect answers decrease it
80% PP score is the passing threshold (but the quiz continues until 100 or questions exhausted)
The PP score is weighted - harder questions have more impact. A student with 100% accuracy sees ~11 questions; 80% accuracy sees ~18 questions.
Architecture
User → App → PowerPath API
↳ Renders question
↳ Submits answer
↳ PowerPath decides next question
The app does NOT implement any quiz logic. PowerPath handles:
Which question to show next
Difficulty adaptation (for PowerPath 100)
Scoring and pass/fail determination
Attempt tracking
Project Structure
File/Folder Purpose src/index.tsBun server entry point with route definitions src/routes/quiz.tsAPI routes that call PowerPath src/lib/config.tsLoads lesson config from OneRoster src/lib/timeback.tsSDK initialization src/components/React UI (Landing, Quiz, Results, AttemptList, AttemptReview) scripts/setup-all.tsCreates org, course, QTI items, and PowerPath lessons samples/questions.json30 questions in JSON format samples/example.xmlReference QTI 3.0 XML format
API Endpoints
Quiz Flow
Endpoint Method Purpose /api/quiz/startPOST Start a new quiz attempt /api/quiz/nextPOST Get the next question /api/quiz/submitPOST Submit an answer /api/quiz/completePOST Finalize the attempt and get results /api/quiz/progressPOST Get current progress for an attempt
Attempt History
Endpoint Method Purpose /api/quiz/attemptsPOST List all attempts for a lesson /api/quiz/attempt-detailsPOST Get detailed results for a specific attempt
Configuration
Endpoint Method Purpose /api/quiz/configGET Get lesson IDs and settings /api/quiz/userGET Get current user info /api/healthGET Health check with setup status /api/timeback/activityPOST Time tracking (Timeback handler)
Example: Quiz Flow
POST /api/quiz/start { lessonType: 'powerpath-100' }
→ PowerPath: createNewAttempt({ student, lesson })
← { lessonId, attemptId, questionCount }
POST /api/quiz/next { lessonId }
→ PowerPath: getNextQuestion({ student, lesson })
← Question data (PowerPath decides which one)
POST /api/quiz/submit { lessonId, questionId, response }
→ PowerPath: updateStudentQuestionResponse(...)
← { isCorrect, score, ... }
POST /api/quiz/complete { lessonId, lessonType }
→ PowerPath: finalStudentAssessmentResponse({ student, lesson }) (quiz only)
← Final results with PP score
Environment Variables
# Timeback API credentials (same for all services)
TIMEBACK_CLIENT_ID = your_client_id
TIMEBACK_CLIENT_SECRET = your_client_secret
TIMEBACK_ENV = staging
# User email for progress tracking
TIMEBACK_USER_EMAIL = your_email@example.com
Features
Attempt History
Users can review past completed attempts:
View all previous attempts with scores
Navigate through each question
See which answers were correct/incorrect
Compare PP score vs raw accuracy
Time Tracking
Time tracking uses the Timeback client SDK in time-only mode:
The client starts an activity at quiz start and calls activity.end({}) on completion
The server handler emits a TimeSpentEvent (no ActivityCompletedEvent)
Results show a “Time tracked” indicator
Idle detection : When the user switches tabs or minimizes the window, the activity is automatically paused via activity.pause() and resumed via activity.resume() on return, so idle time is excluded from the tracked duration
This is separate from PowerPath’s grading - it’s for learning analytics only.
Key Points
No local algorithm - PowerPath handles all quiz logic
Real API calls - Every action goes through PowerPath
Two lesson types - Same code, different behavior based on lessonType
Setup required - Must run bun run setup before the app works
PP score ≠ accuracy - PowerPath 100 uses weighted scoring, not raw percent correct
solid-start
SolidStart app with Timeback SSO authentication and activity tracking.
Quick Start
cp .env.example .env
# Add your Cognito credentials to .env
bun install
bun dev
File Structure
File Purpose src/lib/timeback.tsSDK server instance with SSO config src/routes/api/timeback/[...path].tsCatch-all API route for SDK src/routes/api/auth/sso/callback/timeback.tsCustom OAuth callback src/routes/api/session.tsSession endpoint src/routes/api/signout.tsSign out endpoint src/routes/index.tsxMain page with auth UI
Key Patterns
Server SDK → toSolidStartHandler(timeback) in API routes
Client → SignInButton, Activity from timeback/solid
Session → Server-side store, fetched via /api/session
svelte-kit
SSO authentication and activity tracking with SvelteKit.
Quick Start
cp .env.example .env
# Add your TIMEBACK_SSO_CLIENT_ID and TIMEBACK_SSO_CLIENT_SECRET
bun install
bun run dev
Structure
File Purpose src/hooks.server.tsTimeback request handler src/lib/timeback.tsSSO config + session management src/routes/+page.server.tsPass session to page src/routes/+page.svelteSignInButton + activity demo
Key Patterns
Server hooks — Handle auth routes via svelteKitHandler:
// hooks.server.ts
export const handle = ({ event , resolve }) =>
svelteKitHandler ({ timeback , event , resolve , building })
SignInButton — Pre-styled SSO button:
< script >
import SignInButton from '@timeback/sdk/svelte/SignInButton.svelte'
</ script >
< SignInButton />
Activity tracking — Track learning time:
< script >
import { timeback } from '@timeback/sdk/svelte'
import { onMount } from 'svelte'
let activity = $ state ( undefined )
onMount (() => {
activity = $ timeback ?. activity . start ({ id: 'lesson_1' , name: 'Fractions' , courseCode: 'MATH-101' })
})
</ script >
< button onclick = { () => activity ?. end ({ xpEarned: 100 }) } > Submit </ button >
tanstack-start
SSO authentication and activity tracking with TanStack Start.
Quick Start
cp .env.example .env
# Add your TIMEBACK_SSO_CLIENT_ID and TIMEBACK_SSO_CLIENT_SECRET
bun install
bun dev
File Structure
File Purpose src/lib/timeback.tsServer SDK configuration src/routes/api/timeback/$.tsTimeback API routes src/routes/api/auth/sso/callback/timeback.tsCustom OAuth callback src/routes/api/session.tsSession endpoint src/routes/api/signout.tsSign out endpoint src/routes/index.tsxMain page with SSO demo timeback.config.jsonCourse/app configuration
Key Patterns
Server config — Configure SSO in src/lib/timeback.ts:
export const timeback = await createTimeback ({
env: 'staging' ,
identity: {
mode: 'sso' ,
clientId: process . env . TIMEBACK_SSO_CLIENT_ID ! ,
clientSecret: process . env . TIMEBACK_SSO_CLIENT_SECRET ! ,
redirectUri: 'http://localhost:5174/api/auth/sso/callback/timeback' ,
onCallbackSuccess : ({ user , redirect }) => {
setSession ({ id: user . id , email: user . email })
return redirect ( '/' )
},
getUser : () => getSession (),
},
})
API routes — Mount Timeback handlers:
// src/routes/api/timeback/$.ts
import { toTanStackStartHandler } from '@timeback/sdk/tanstack-start'
export const Route = createFileRoute ( '/api/timeback/$' )({
server: { handlers: toTanStackStartHandler ( timeback ) },
})
Client — Use the React adapter:
import { SignInButton , TimebackProvider , useTimeback } from '@timeback/sdk/react'
function App () {
return (
< TimebackProvider >
< SignInButton />
</ TimebackProvider >
)
}
Next Steps
Quickstart Get started with integration
SDK Overview Learn about SDK features
Configuration Full config reference
Developer Program Apply for access