Quickstart
Install
Section titled “Install”npm i @ltikit/core…plus one storage adapter and (optionally) one framework binding — chosen below.
1. Create the LTIkit instance
Section titled “1. Create the LTIkit instance”Pick your storage — any of these work the same. (All options: Storage adapters.)
import { PrismaClient } from '@prisma/client'import { createLti, staticKeyStore } from '@ltikit/core'import { prismaPlatformStore, prismaNonceStore } from '@ltikit/adapter-prisma'
const prisma = new PrismaClient() // SQLite for zero external service, or Postgres/MySQL
export const lti = createLti({ keys: staticKeyStore({ privateKeyPem: process.env.LTI_TOOL_PRIVATE_KEY!, kid: process.env.LTI_TOOL_KEY_ID ?? 'ltikit-key-1', publicJwk: JSON.parse(process.env.LTI_TOOL_PUBLIC_JWK!), }), platforms: prismaPlatformStore(prisma), nonces: prismaNonceStore(prisma),})Copy the two models first — see Prisma adapter.
import { createClient } from '@supabase/supabase-js'import { createLti, staticKeyStore } from '@ltikit/core'import { supabasePlatformStore, supabaseNonceStore, type SupabaseLike } from '@ltikit/adapter-supabase'
const admin = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_SERVICE_ROLE_KEY!, { auth: { persistSession: false },})const client = admin as unknown as SupabaseLike
export const lti = createLti({ keys: staticKeyStore({ /* … */ }), platforms: supabasePlatformStore(client), nonces: supabaseNonceStore(client),})Full setup (tables + RLS): Supabase adapter.
import { createLti, staticKeyStore } from '@ltikit/core'import { redisNonceStore, fromUpstash } from '@ltikit/adapter-redis'import { Redis } from '@upstash/redis'
export const lti = createLti({ keys: staticKeyStore({ /* … */ }), nonces: redisNonceStore(fromUpstash(Redis.fromEnv())), // fast serverless nonces platforms: prismaPlatformStore(prisma), // durable — Prisma / Supabase / your own})import { createLti, staticKeyStore } from '@ltikit/core'import { MemoryNonceStore, MemoryPlatformStore } from '@ltikit/adapter-memory'
export const lti = createLti({ keys: staticKeyStore({ /* … */ }), platforms: new MemoryPlatformStore([/* seed Platform[] */]), nonces: new MemoryNonceStore(),})2. Wire the routes
Section titled “2. Wire the routes”import { oidcLogin } from '@ltikit/next'import { lti } from '@/lib/lti'export const POST = oidcLogin(lti, { redirectUri: `${process.env.APP_URL}/api/lti/launch` })import { launch, sessionRedirect } from '@ltikit/next'import { ltiIdentity } from '@ltikit/core'import { lti } from '@/lib/lti'export const POST = launch(lti, async (result) => { const id = ltiIdentity(result.claims) // → create user + session (see Auth integration) return sessionRedirect({ to: `${process.env.APP_URL}/home`, cookies: [/* your session cookie */] })})import { jwks } from '@ltikit/next'import { lti } from '@/lib/lti'export const GET = jwks(lti)import { oidcLogin, launch, jwks } from '@ltikit/hono'import { ltiIdentity } from '@ltikit/core'
app.post('/api/lti/login', oidcLogin(lti, { redirectUri: `${APP_URL}/api/lti/launch` }))app.post('/api/lti/launch', launch(lti, async (result, c) => c.redirect('/home')))app.get('/.well-known/jwks.json', jwks(lti))3. Database + keypair
Section titled “3. Database + keypair”- Apply the adapter schema for the store you picked:
- Prisma — copy the two models into your
schema.prisma, thennpx prisma migrate dev --name add_ltikit. - Supabase —
npx @ltikit/adapter-supabase > supabase/migrations/0001_ltikit.sql. - Redis — nothing to migrate (keys are created on write); pair with a durable
PlatformStore. - Memory — nothing to set up (dev/tests only).
- Prisma — copy the two models into your
- Generate an RS256 keypair for
LTI_TOOL_PRIVATE_KEY/LTI_TOOL_PUBLIC_JWK.
4. Register with the LMS
Section titled “4. Register with the LMS”Point your LMS at the routes (JWKS = /.well-known/jwks.json, OIDC login = /api/lti/login, redirect URI =
/api/lti/launch) and add a platform row. See LMS registration.
Next steps
Section titled “Next steps”- How it fits together — required core vs your choices.
- Auth integration — turn the launch into a real session.
- Running in an iframe — CSP + cookies for LMS embedding.