Starter Templates
| Template | Framework | Description |
|---|---|---|
nextjs-app-router | Next.js | App Router with SSO and activity tracking |
nuxt | Nuxt 3 | Server middleware with Vue composables |
svelte-kit | SvelteKit | Hooks-based integration with stores |
solid-start | SolidStart | Middleware with primitives |
tanstack-start | TanStack Start | File-based routes with React |
express | Express | Standalone API server |
express-auth0 | Express + Auth0 | Custom auth mode with Auth0 |
express-supabase | Express + Supabase | Custom auth mode with Supabase |
bun-react | Bun + React | Minimal SSO example |
bun-react-identity-only | Bun + React | Identity-only mode (no activity tracking) |
bun-react
Source: examples/bun-react
/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
Structure
| File | Purpose |
|---|---|
src/index.ts | Bun server + Timeback routes |
src/lib/timeback.ts | SSO config + session management |
src/App.tsx | SignInButton + activity demo |
src/frontend.tsx | React entry point |
Key Patterns
Native handler — Mount Timeback routes:bun-react-full
Source: examples/bun-react-full
timeback.api
(an escape hatch for calling Timeback services like OneRoster).
Quick Start
Structure
| File | Purpose |
|---|---|
src/index.ts | Bun server + Timeback routes |
src/lib/timeback.ts | SSO config + session management |
src/App.tsx | SignInButton + activity demo |
src/frontend.tsx | React entry point |
Key Patterns
Native handler — Mount Timeback routes:bun-react-gradeless
Source: examples/bun-react-gradeless
courseCode instead of (subject, grade) for course identity.
Quick Start
Grade-less Course Configuration
Apps without grade levels usecourseCode as the course identifier:
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:
examples/bun-react):
Structure
| File | Purpose |
|---|---|
src/index.ts | Bun server + Timeback routes |
src/lib/timeback.ts | SSO config + session management |
src/App.tsx | SignInButton + activity demo |
timeback.config.json | Grade-less course configuration |
bun-react-identity-only
Source: examples/bun-react-identity-only
createTimebackIdentity() for apps that only need Timeback SSO without the full SDK.
Quick Start
Structure
| File | Purpose |
|---|---|
src/index.ts | Bun server + Timeback routes |
src/lib/timeback.ts | SSO config + session management |
src/App.tsx | SignInButton + session display |
src/frontend.tsx | React entry point |
Key Differences from Full SDK
- Uses
createTimebackIdentity()instead ofcreateTimeback() - No
apicredentials required - No
timeback.config.jsonrequired - Only identity routes are available (no activity tracking)
Key Patterns
Identity-only server — No API credentials needed:express
Source: examples/express
Quick Start
Verify Routes
Run the verification script to test all routes:Routes
| Method | Path | Description |
|---|---|---|
| GET | /health | Health check |
| GET | /api/timeback/identity/signin | Initiate SSO sign-in |
| GET | /api/timeback/identity/callback | SSO callback handler |
| GET | /api/timeback/identity/signout | Sign out |
| POST | /api/timeback/activity | Submit activity events |
Testing
Integration Options
The SDK provides two ways to integrate with Express:Option 1: Middleware (recommended)
Option 2: Router mounting
express-auth0
Source: examples/express-auth0
auth0 Node.js SDK.
Architecture
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
Environment Variables
Createbackend/.env from backend/.env.example:
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
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
Project Structure
API Routes
| Method | Route | Description |
|---|---|---|
| GET | /health | Health check |
| POST | /auth/login | Login with email/password |
| POST | /auth/logout | Clear session cookie |
| GET | /api/session | Get current user |
| GET | /api/timeback/user/me | Timeback user profile |
| POST | /api/timeback/activity | Submit activity events |
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
”Auth0 is not configured”
- Check
AUTH0_DOMAIN,AUTH0_CLIENT_ID,AUTH0_CLIENT_SECRETin.env - Domain should be just
your-tenant.auth0.com(nohttps://)
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
/authand/apito 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
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
getEmailcallback reads email from the request - SDK resolves Timeback user - When submitting activity, SDK looks up the Timeback user by email
- 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
- Allowed Callback URLs:
- Ensure the Database connection is enabled for the SPA (email/password hosted by Auth0)
2. Environment Setup
.env with your credentials.
3. Install and Run
Launch-gated URL
Visithttp://localhost:5173/timeback/signin to simulate the Timeback launch URL.
Commands
| Command | Description |
|---|---|
just install | Install backend + frontend |
just dev | Start backend + frontend |
just dev-backend | Start backend only |
just dev-frontend | Start frontend only |
just setup | Copy .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 | POST | Submit activity to Caliper |
/api/timeback/user/me | GET | Get Timeback user profile |
/api/timeback/user/verify | GET | Verify Timeback user status |
Session Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/health | GET | Health check |
/api/user/me | GET | Auth0 user |
Project Structure
express-supabase
Source: examples/express-supabase
Architecture
Setup
1. Install dependencies
2. Configure environment
backend/.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
- Frontend: http://localhost:5173
- Backend: http://localhost:3001
Timeback Integration
The SDK is configured with custom identity mode, reading the user’s email from the session cookie:Available Commands
| Command | Description |
|---|---|
just install | Install all dependencies |
just setup | Create .env from template |
just dev | Start both servers |
just dev-backend | Start backend only |
just dev-frontend | Start frontend only |
nextjs-app-router
Source: examples/nextjs-app-router
Quick Start
Structure
| File | Purpose |
|---|---|
src/app/api/timeback/[...timeback]/ | Timeback request handler |
src/app/api/auth/sso/callback/timeback/ | Custom OAuth callback |
src/lib/timeback.ts | SSO config + session management |
src/app/page.tsx | SignInButton + activity demo |
Key Patterns
API routes — Handle auth routes viatoNextjsHandler:
nuxt
Source: examples/nuxt
Setup
Make sure to install dependencies:Development Server
Start the development server onhttp://localhost:3000:
Production
Build the application for production:solid-start
Source: examples/solid-start
Quick Start
File Structure
| File | Purpose |
|---|---|
src/lib/timeback.ts | SDK server instance with SSO config |
src/routes/api/timeback/[...path].ts | Catch-all API route for SDK |
src/routes/api/auth/sso/callback/timeback.ts | Custom OAuth callback |
src/routes/api/session.ts | Session endpoint |
src/routes/api/signout.ts | Sign out endpoint |
src/routes/index.tsx | Main 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
Source: examples/svelte-kit
Quick Start
Structure
| File | Purpose |
|---|---|
src/hooks.server.ts | Timeback request handler |
src/lib/timeback.ts | SSO config + session management |
src/routes/+page.server.ts | Pass session to page |
src/routes/+page.svelte | SignInButton + activity demo |
Key Patterns
Server hooks — Handle auth routes viasvelteKitHandler:
tanstack-start
Source: examples/tanstack-start
Quick Start
File Structure
| File | Purpose |
|---|---|
src/lib/timeback.ts | Server SDK configuration |
src/routes/api/timeback/$.ts | Timeback API routes |
src/routes/api/auth/sso/callback/timeback.ts | Custom OAuth callback |
src/routes/api/session.ts | Session endpoint |
src/routes/api/signout.ts | Sign out endpoint |
src/routes/index.tsx | Main page with SSO demo |
timeback.config.json | Course/app configuration |
Key Patterns
Server config — Configure SSO insrc/lib/timeback.ts: