Learner UI registry
Cursare publishes the learner-facing interface as installable source. Use the focused components when your application owns data and effects, or use the server adapter when Cursare should deliver the published course document.
Open the component showcase or browse the public source.
Install components
Install the complete learner platform:
bunx shadcn@4.14.0 add https://cursare.com/r/blocks.json
Or install only one surface:
bunx shadcn@4.14.0 add https://cursare.com/r/course-card.json
bunx shadcn@4.14.0 add https://cursare.com/r/course-player.json
For repeated installs, register the namespace in components.json:
{
"registries": {
"@cursare": "https://cursare.com/r/{name}.json"
}
}
The same registry works with shadcn projects and COSS/Base UI projects. The command copies the implementation into your repository, including the Cursare-owned primitives required by that surface.
Import the installed styles once:
@import "./components/cursare/styles.css";
@import "./components/cursare/composer/viewer/styles.css";
The second import is required by the course player and by the complete blocks item.
Choose the delivery boundary
| Mode | Install | Your application supplies |
|---|---|---|
| Host-owned | course-player | Published document, routes, persistence, grading, polls, and notes |
| Cursare API | cursare-course-player | A server-only organization API key and the content ID |
| Headless runtime | course-player | A short-lived learner token issued by your backend |
The host-owned player contains no Cursare endpoint or credential. It is the right boundary when your application already has its own backend.
Load published content from Cursare
Install the API adapter:
bunx shadcn@4.14.0 add https://cursare.com/r/cursare-course-player.json
Configure the key once in server-only code:
import { createCursareCoursePlayer } from "@/components/cursare/cursare-course-player"
const apiKey = process.env.CURSARE_API_KEY
if (!apiKey) throw new Error("CURSARE_API_KEY is required")
export const CursarePlayer = createCursareCoursePlayer({ apiKey })
export default function CoursePage() {
return <CursarePlayer contentId="content-id" />
}
The adapter calls GET /api/v1/contents/{id}/learner. The response contains the published learner document and removes author-only answer keys.
Use Cursare as a headless learner runtime
For an embedded experience with Cursare-managed access, progress, quizzes, and certificates, exchange the organization credential on your backend:
const session = await fetch("https://api.cursare.com/v1/learner-runtime/sessions", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CURSARE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ userId, rootContentId, origin: "https://app.example.com" }),
}).then((response) => response.json())
Send only session.data.token to that origin. The browser can then load the course and progress from GET /learner-runtime/{rootContentId}, update a stable section through PATCH /learner-runtime/{rootContentId}/progress, submit quizzes to /attempts, and retrieve the completed credential from /certificate. Tokens expire after 15 minutes; renew them through your backend before expiration.
Public source boundary
The public repository contains only learner rendering and the UI primitives it requires. Dashboard code, authentication, database adapters, authoring tools, Markdown internals, and answer-key collection stay private.
The stable URLs above follow the supported release. To schedule upgrades explicitly, pin https://cursare.com/r/v1/{name}.json, rerun the command, and review the source diff.