This project provides two major capabilities:
- QTI 2.x Players β Production-ready item and assessment players with extensibility and theming
- PIE β QTI Transformation Framework β Bidirectional transforms between QTI 2.2 and PIE, with CLI, web app, and IMS Content Package support
π Live Examples
Project Status: QTI 2.x players are production-ready. Transform framework is under active development. See STATUS.md for details.
Warning
While I believe the QTI player is production ready, we're still sticking to 0.1.x for a while, and we may make API changes between versions. I don't foresee a lot of that, but nevertheless, until this project has been used in the wild for a while, we may need some tweaks here and there to make the API good and meanwhile it's best to keep the code clean and unbothered with shims and other backwards compatibility constructs. Once we're at 1.0.0, we'll make stronger commitments for the API. But, let us know if you plan to use this for a non-trivial/ production system, and we can move such commitments forward.
PIE (Portable Interactions and Elements) is a complete framework for playing and authoring assessment items, maintained by Renaissance Learning with implementation partner MCRO.
Many Renaissance partners exchange content in QTI format, so bidirectional QTI β PIE transformation is essential. This project open sources that transformation framework for partners and the broader community.
We also built a spec-complete QTI 2.x player because a modern, open-source option was missingβand we needed one for previewing, analysis, and "convert then render" workflows.
Status: Production-ready
Full-featured players for rendering QTI 2.x assessment content in the browser.
Renders and scores individual QTI items:
- 21 interaction types β All QTI 2.2 interactions supported
- 45 response processing operators β Complete client-side scoring
- Role-based rendering β Candidate, scorer, author, tutor, proctor, testConstructor
- Adaptive items β Multi-attempt workflows with progressive feedback
- Accessible β Full keyboard navigation and screen reader support (follows WCAG 2.2 Level AA guidelines)
- Iframe isolation mode β Optional secure rendering for untrusted content
Orchestrates multi-item assessments:
- Navigation modes β Linear (sequential) and nonlinear (free navigation)
- Sections & hierarchy β Nested sections with rubric blocks
- Selection & ordering β Random item selection and shuffling per QTI spec
- Time limits β Countdown timers with warnings and auto-submission
- Item session control β Max attempts, review/skip, response validation
- State persistence β Auto-save with resume capability
- Outcome processing β Scoring templates (total, weighted, percentage, pass/fail)
- Backend adapter β Optional server-side scoring and secure data handling
The player architecture separates QTI logic from UI rendering:
- Plugin system (
QTIPlugin) β Register custom extractors, components, and lifecycle hooks - Registries β Priority-based
ExtractionRegistryandComponentRegistry - Typesetting hook β Host-provided math rendering (KaTeX adapter included)
- Custom operators β Support for
<customOperator>elements
See the ACME Likert plugin for a complete extensibility example.
Components render via web components (Shadow DOM) with a CSS variable contract:
- Theme tokens β DaisyUI-compatible variables (
--p,--a,--b1,--bc, etc.) ::part()hooks β Stable part names for host-side style refinement- Zero-CSS fallback β Components render correctly with no host styles
See STYLING.md for the full styling contract.
The player UI supports multiple languages with runtime locale switching:
- Type-safe translations β TypeScript autocomplete for all message keys
- Runtime switching β Change language without page reload
- Custom translations β Clients provide complete locale bundles or override specific strings
- Small bundle β <10 KB gzipped (core + default locale)
See @pie-qti/qti2-i18n for the complete i18n API and custom translation examples.
Status: Under active development
Bidirectional transformation between QTI 2.2 XML and PIE JSON.
QTI β PIE (@pie-qti/qti2-to-pie)
- Lossless round-trip when QTI originated from PIE
- Best-effort semantic transformation otherwise
- Vendor extension system for custom QTI variants
PIE β QTI (@pie-qti/pie-to-qti2)
- Lossless reconstruction when PIE contains embedded QTI
- Generator registry for custom PIE model handling
- IMS Content Package generation (
imsmanifest.xml)
Interactive web UI for transformations:
- Upload β Single files or ZIP packages (including nested ZIPs)
- Analyze β Discover items, count interactions, report issues
- Transform β Batch convert with progress reporting
- Preview β Side-by-side QTI and PIE rendering
Storage is pluggable with filesystem (default), S3, or database backends via configuration.
Command-line tool for batch operations:
# Transform a single item
bun run pie-qti -- transform input.xml --format qti22:pie --output output.json
# Analyze QTI content
bun run pie-qti -- analyze ./content-package/
# See all commands
bun run pie-qti -- --help# Install dependencies
bun install
# Build all packages
bun run build
# Run tests
bun run test
# Lint and typecheck
bun run lint
bun run typecheck
# E2E tests (Playwright)
bun run test:e2eTo test with pie-players locally, clone both repos side-by-side. The postinstall script auto-links them.
bun run build:pages
bun run preview:pages
# Open http://localhost:4173/pie-qti/- Architecture Guide β System design, package map, extensibility, theming, and security
- Item Player β API, interactions, accessibility
- Assessment Player β Navigation, scoring, backend integration
- Styling Contract β Theming with CSS variables and ::part
- Example App β Demo application with all interactions
- Transformation Guide β Bidirectional transform overview
- Configuration Guide β Storage backends, plugins, and environment setup
- Migration Guide β Upgrading from legacy storage to new architecture
- Transform App β Web UI for transformations
- CLI β Command-line batch operations
- QTI β PIE β QTI to PIE transformer
- PIE β QTI β PIE to QTI transformer
- IMS Content Packages β Manifest generation
- Custom Generators β Adding PIE model support
- ACME Likert Plugin β Player extensibility example
ISC License β see LICENSE

