INTEGRATION

Integrate P2LRN with your platform

The Player manages packaging and playback. Your platform retains users, permissions, progress, scores, protected resources, and data that should not travel within the course.

Before integrating

Load the Player using the chosen installation guide. This page is part of a <p2lrn-player> now available and focuses on communication with your platform.

AI and LMS Connectors

For MCP connectors for ChatGPT, Claude, Grok, and on-premises applications, or for LMS architecture and LTI 1.3, see the connectors documentation.

Architecture

.p2lrn→Player↕events / Host Adapter↕application↕server and persistence

Host Adapter

Host Adapter is the bridge between the Player and your platform services. Implement only the features your integration needs and maintain authentication and authorization on the server.

loadState(context)

Recover the last snapshot of an activity or progression so you can resume.

saveState(state, context)

Save the current snapshot. It should not be confused with an analytical log.

reportScore(score, context)

Provides normalized scores from questionnaires, SCORM or H5P when the runtime has them.

emitEvent(event, context)

Delivers the canonical flow p2lrn:* in order for analytics, auditing or integration.

resolveResourceUrl(request, context)

Resolves protected resources that your platform has already authorized and verified.

The learner's identity and current attempt belong to your application. Combine them in your backend with packageId, contentRoot and entityId; Do not put personal information inside the package.

JavaScript
const adapter = P2LRN.createHostAdapter({
  async loadState(context) { return loadProgress(context); },
  async saveState(state, context) { await saveProgress(state, context); },
  async reportScore(score, context) { await saveScore(score, context); },
  async emitEvent(event, context) { await recordEvent(event, context); },
  async resolveResourceUrl(request, context) {
    const url = await authorizeResource(request, context);
    return url ? {url, verified: true, seekable: request.seekable === true} : null;
  },
});
document.querySelector('p2lrn-player').adapter = adapter;
The functions in the example belong to your application.

P2LRN defines the adapter contract, but does not enforce path names or a specific database.

Live capabilities: Capability Broker

Host Adapter continues to be the frontier for state, notes, events, and resources. Optional live services connect via Capability Broker, so the packet declares a semantic need and the host decides which actual provider satisfies it.

Package

Declare the capacity and permitted operations. It does not contain endpoints, tokens, users or credentials.

Player

Negotiate the capacity and deliver to the renderer a invokeCapability() restricted; the renderer does not receive the full broker.

Host

Register providers and authorize each invocation. The same contract can map to HTTP, WebSocket, SSE, a local service or another implementation.

The first collaboration capability uses collaboration.room with join, send, listen, snapshot and leave. View the full collaboration guide.

JavaScript
const provider = P2LRN.createHttpCollaborationProvider({
  endpoint: '/api/p2lrn/collaboration',
  getHeaders: () => ({ Authorization: 'Bearer ' + token })
});

player.capabilityBroker = P2LRN.createCapabilityBroker({
  providers: [provider],
  authorize: ({capabilityId}) =>
    capabilityId === 'collaboration.room'
});

Offline, retries and reconciliation

createOfflineHostAdapter() maintains Host Adapter v1 and adds local staging status plus a tidy outbox for status, scores, and events. With storageNamespace or createIndexedDbOfflineStore() the host can persist one explicit partition per user/session.

  • Snapshots of the same context are coalesced last; Events and scores maintain order.
  • Delivery is at-least-once. offlineDeliveryId allows the server to deduplicate effects when it needs idempotence.
  • createOfflineSyncController() can react to online/offline with limited backoff. It does not create services, system tasks or background processes.
  • Note authority, identity, and multi-device conflicts continue on the server.
JavaScript
const offline = P2LRN.createOfflineHostAdapter({
  remote: hostAdapter,
  storageNamespace: hostOpaqueSession
});
player.adapter = offline;
const sync = P2LRN.createOfflineSyncController({adapter: offline});

Verified shared resources

A reusable remote representation declares expectedDigest SHA-256. The Player does not trust the packet URL: the Host Adapter or a local resolver must deliver verified bytes.

createMemorySharedResourceStore()

Minimum content-addressed reference for tests/local: a single digest preserves a single object.

createMemoryResourceLibrary()

In-memory verifiable library.

createCacheStorageResourceLibrary()

Persistence in Cache Storage between browser sessions, always indexed by digest.

createResourceLibraryResolver()

Searches locally first, checks SHA-256 before inserting a miss and returns {verified:true}.

createResourceLibraryCapabilityProvider()

Exposes only metadata using resource.library: search, describe and has; the bytes remain behind the resolver.

Studio can select a library entry using its property resourceLibrary and materializeSharedResource() adds an embedded fallback to the same Resource when non-network portability is needed.

Verified course cache

createCacheStoragePackageCache() allows you to preserve a .p2lrn complete after it passes normal manifest, network, and integrity checks. It is checked again when you open it.

cachePackageURL() and openCachedPackage() they are opt-in; The cached package does not contain identity, notes or outbox. The host controls quota, retention, and deletion.

Authoritative reference host

For a Node backend, @p2lrn/toolkit/host exports createReferenceAuthoritativeHost() along with in-memory/JSON stores. The reference separates the reported score from an authoritative decision produced by grade(), supports state conflict policies and deduplicates offline deliveries by offlineDeliveryId.

It is a reference implementation to integrate the trust boundary; The platform that integrates it is still responsible for authentication, authorization, multi-user partitioning and adequate storage.

Private content

The learner's identity and secrets do not belong in the package. Your server authenticates and authorizes the request and can serve a temporary URL or resolve the resource using the Host Adapter.

Isolated execution environments

If a SCORM or H5P is within the own .p2lrn, you don't have to publish it separately. The Player opens the nested package, prepares its files in memory, and automatically creates a sandbox iframe with opaque origin by default, even if the Player is served from a CDN.

.p2lrn→SCORM / H5P incluido→Player→ephemeral sandbox→activity
runtime-base-url it is not required for SCORM or H5P.

Normal behavior is automatic, also in supported local HTML releases. The internal sandbox does not receive allow-same-origin, so the activity code does not share the origin of your application.

In H5P, if the included file does not have all its libraries, the Player resolves the dependencies from the H5P catalog located next to its distribution, loads them from the application context and transfers them to the sandbox. Those libraries run within the same opaque environment as the content.

Optional external runtime

Configure runtime-base-url only when you want to deliberately use a managed runtime service on another domain, subdomain, or port. That mode is still available for server-managed H5P sessions and deployments with their own policies.

HTML · optional configuration
<p2lrn-player
  src="https://content.example.com/course.p2lrn"
  runtime-base-url="https://runtime.example.net/p2lrn/runtime/">
</p2lrn-player>

The local HTML releases of cmi5, Tin Can, Common Cartridge, and IMS Content Package also have automatic sandboxing. The cmi5 adapter offers synthetic identity and state-separated preview using the Host Adapter; It does not replace a real LMS/LRS nor does it certify complete CMI5 compliance. Scripts that require stable HTTP URLs, dynamic loading, co-origin frameworks, or external services may require a managed runtime and additional resources. The browser does not run PHP, JSP, ASP, or Flash.

Persistence of progress and metrics

When the course uses progression, the Player loads its state with loadState, updates it from rendering, completion and scoring and saves it again with saveState. SCORM internal statements, H5P or questionnaires use the same contract, but with different activity contexts.

Status, grade and analytics are different channels.

Use saveState to resume, reportScore for notes and emitEvent for history/telemetry. The guide Metrics and analytics shows the full model and available fields by content type.

Save, Reader and Import Security: Your Website Responsibility

P2LRN does not replace the authentication or authorization of the platform that integrates it. The command p2lrn-studio setup generates the technical endpoints, but it doesn't protect them with your site's accounts, roles, or permissions. Before enabling them for real users, your server must apply its own checks to POST /api/p2lrn/studio/save, POST /api/p2lrn/studio/read and POST /api/p2lrn/studio/import.

Identity and permissions

Verify the session or token on the server. Check the teacher/editor or administrator role and the permissions on the course and the specific center; denies access with 401 or 403. Hiding buttons in Studio does not constitute authorization.

Request Protection

If you use session cookies, apply CSRF and origin checking according to your framework. Maintain a restrictive CORS policy, HTTPS, and request and size limits for documents, ZIP, and packages.

Storage and processing

The host application sets the authorized folder or storage, its quotas, and isolation between users or centers. Do not allow the browser to choose absolute paths or overwrite foreign packages. Treat imported files as untrusted.

Identity and grades

SCORM/H5P content runs in isolation. They do not receive cookies, secrets or direct access to the site's database. Results sent by the Player should not be considered accredited scores without server validation.

Secuencia correcta: browser → authentication and authorization of your site → CSRF controls, size and destination → features @p2lrn/studio/server → storage of your platform. These requirements apply equally using npm or CDN. If you only create, edit, and download files in the browser without server endpoints, these three paths are not necessary.

CORS

If the package or a resource is located in another source, the server must allow it to be read from the browser. CORS is not a substitute for user authentication or authorization.

Final check

  • PACKAGEThe manifest, network, and resources are verified successfully.
  • PLAYERThe events ready and rendered They arrive without error.
  • STATUSProgress and score are preserved outside the package.
  • PRIVATEThe course does not contain credentials or learner identity.
  • RUNTIMESCORM, H5P, and supported local HTML use automatic isolation; any expressly configured external runtime is accessible.