NPM / STUDIO
Studio with NPM
This guide only covers integrating Studio as a project dependency. It includes the browser part and, when you need it, the server services for saving and importing.
1. Install dependencies
Install Studio and Player in the same project so that the editor can use the Player during learner View.
npm install @p2lrn/studio@0.5.0-alpha.11 @p2lrn/player@0.5.0-alpha.11The Studio and Player versions must be aligned.
2. Register Studio in the app
Import Studio once from client code. Then you can use <p2lrn-studio> in the interface.
import '@p2lrn/studio';<p2lrn-studio></p2lrn-studio>With this minimal setup you can create a course, open a file or URL, edit, preview and download a new .p2lrn.
3. Open an initial course
The attribute src It is optional. Use it when the application already knows which course the editor should open.
<p2lrn-studio src="/courses/course.p2lrn"></p2lrn-studio>The attribute src It is optional. If you do not define it, the user can create a new course from the interface.
4. Generate server routes
After installing Studio, run the setup once within your project. You don't have to write the Save, Reader and Import paths one by one.
npx p2lrn-studio setupThe command locates the root of the project, detects the technology and materializes the three operations: /api/p2lrn/studio/save, /api/p2lrn/studio/read and /api/p2lrn/studio/import. Also create the courses folder.
In JavaScript/TypeScript backends routes directly call @p2lrn/studio/server. In PHP, Python, Ruby, .NET, Java, Go, and Rust, setup generates the framework handler and a local Node bridge that runs Reader and import. Another server is not created or raised.
p2lrn-studio setup creates Save, Reader, and Import, but does not automatically add user authentication or permissions. On your application server you must check who requests each operation and if they have permission to edit that course or center, as well as apply CSRF when using cookies, size limits and authorized storage destinations. These checks must be done before invoking the P2LRN helpers. Consult the integration and security guide. The generated example does not replace your application's permissions system.
5. Tell Studio the generated routes
These attributes only tell the component where the routes that setup has already created are. They do not replace the creation of the backend files.
<p2lrn-studio
src="/courses/course.p2lrn"
save-endpoint="/api/p2lrn/studio/save"
reader-endpoint="/api/p2lrn/studio/read"
import-endpoint="/api/p2lrn/studio/import"
course-path="course">
</p2lrn-studio>save-endpointGenerated path to save the exported package.
reader-endpointGenerated path that Reader uses to analyze documents.
import-endpointGenerated path to convert external educational packages to P2LRN.
course-pathLogical save path. The default value is course.
6. Why you need to know technology
Studio uses the same three operations in all cases, but each backend declares its routes differently. Detection is used to generate the correct files for that project.
Create routes within app/api/....
Create a controller inside the structure src/.
Prepares controllers and, where applicable, route definition.
Prepare views, routers or blueprints compatible with each environment.
Generates the handler, controller or endpoint in the format expected by the project.
See all recognized technologies
Next.js, Express, Nest, Fastify, Hono, SvelteKit, Nuxt, Astro, Remix, React Router, Node.js, PHP, Laravel, Symfony, Django, FastAPI, Flask, Rails, ASP.NET, Spring, Go, Rust and a generic integration.
7. Server auxiliary functions
If your server uses JavaScript or TypeScript, the package exposes helper functions to implement save, reader, and import operations.
import {
handleP2LRNStudioSave,
handleP2LRNStudioReader,
handleP2LRNStudioExternalImport,
} from '@p2lrn/studio/server';Protect these routes with your application's authentication and authorization. The browser should not be able to freely decide server write paths.
8. Component API
createCourse(options)Create a new course. options also admits author, createdAt, license and copyrightHolder.
openFile(file) / openUrl(url)They open a local or remote package.
setMode('edit' | 'preview')Switch between editing and learner View.
addUnit() / addLesson() / addContent()They add structure and content.
resourceLibraryOptional property. Assign an object with list() and get(digest) to enable the shared library.
materializeSharedResource(activityId)Converts a digest-pinned reference to an embedded fallback using the bytes of the connected library.
download() / saveCourse()Download or send the package to the configured save endpoint.
exportOfflineAssignment() / downloadOfflineAssignment()They generate the self-reproducing delivery of Windows or portable ZIP.
reviewOfflineResult(file)Validate and present a .p2lrn-result returned by the learner.
const studio = document.querySelector('p2lrn-studio');
studio.resourceLibrary = resourceLibrary;9. Events
p2lrn-studio-createA course has been created.
p2lrn-studio-openA package has been opened.
p2lrn-studio-downloadA package has been downloaded.
p2lrn-studio-saveA server save has completed.
p2lrn-studio-offline-exportAn offline delivery has been generated/downloaded; includes format, assignmentId and contentRoot.
p2lrn-studio-offline-reviewAn offline result has been reviewed; exposes completeness/match status and intent.