Skip to content

Add Common Cartridge (.imscc) export for Canvas LMS import#2

Open
daTechGuy wants to merge 6 commits intojtangen:mainfrom
daTechGuy:imscc-canvas-only
Open

Add Common Cartridge (.imscc) export for Canvas LMS import#2
daTechGuy wants to merge 6 commits intojtangen:mainfrom
daTechGuy:imscc-canvas-only

Conversation

@daTechGuy
Copy link
Copy Markdown

Summary

  • Adds a new export path that bundles a generated course as an IMS Common Cartridge 1.1 .imscc file, suitable for native import into Instructure Canvas.
  • Each chapter becomes a Canvas module containing the reading HTML page, QTI 1.2 quizzes (practice + in-class), QTI weekly challenge (MCQ subset), the slides PPTX, infographic JPG, a teaching-resources DOCX (discussions + activities), and one native discussion topic per discussionData entry.
  • Course title and description are surfaced via Canvas's proprietary course_settings/ extension so the description appears in the Syllabus tab, not just the manifest LOM.

What's in the cartridge

Source field Cartridge resource Canvas surface
htmlContent webcontent Page (Modules)
practiceQuizData (markdown) QTI 1.2 assessment Quizzes
inClassQuizData QTI 1.2 assessment Quizzes
weeklyChallengeData QTI 1.2 assessment (mcq / two-stage / boss / confidence-weighted only) Quizzes
slidesJson webcontent (PPTX file) Module item
infographicDataUri webcontent (JPG) Module item
discussionData[] imsdt_xmlv1p1 (one per prompt) Discussions + module item
discussionData + activityData webcontent (DOCX) Module item
courseTitle + courseOverview Canvas course_settings/ Course title + Syllabus tab body
audioUrl skipped — (blob URL is non-persistent; same as existing handleDownloadAll)

Notes / known constraints

  • Lossy QTI conversion. Weekly challenge assertion-reason, agreement-matrix, and slider-estimation question types don't have clean QTI 1.2 equivalents — they're skipped from the gradeable assessment. The MCQ-shaped subset (mcq, two-stage, boss, confidence-weighted) converts cleanly.
  • Interactive HTML quiz/challenge omitted. Canvas's Page sanitizer strips inline <script>, so the rich single-page-app quiz UI cannot survive import. The standalone "Publish Course" HTML viewer remains the right home for that UX.
  • Quizzes import unpublished. Standard Canvas behavior — bulk-publish via Modules → ⋮ → "Publish module and all items."
  • CC 1.1 namespaces used throughout (Canvas's best-tested profile).

New / changed files

  • src/services/export/imsccExporter.ts — new, core exporter (manifest, QTI, IMSDT, course settings)
  • src/services/export/teachingResourcesDocx.ts — new, extracted from ExportPage so both the per-chapter download and the IMSCC bundle share it
  • src/pages/ExportPage.tsx — new "Export for Canvas (.imscc)" button + handler, and a small refactor where the teaching-resources docx logic moved out
  • src/fixtures/demoCourse.ts + src/pages/LandingPage.tsxoptional "Load demo course" path for testing the export without an LLM round-trip. Happy to drop these from the PR if you'd rather keep the fixture out of the main app.

Test plan

  • Type-checks cleanly (tsc -b exit 0); ESLint clean for the new code
  • Round-tripped a fixture course through Canvas Free for Teachers: module tree renders, all QTI quizzes import (unpublished), reading pages render, slides PPTX is downloadable, infographic shows, teaching-resources DOCX previews + embeds, native discussion topic appears under Discussions, course title and Syllabus body populate from course_settings/
  • Tested with a real LLM-generated course (used a demo fixture for iteration speed; would appreciate a sanity check on a real course before merging)

🤖 Generated with Claude Code

claw and others added 6 commits May 7, 2026 14:37
Bundles each generated chapter as a learning module: reading HTML,
practice quiz (QTI + interactive HTML), in-class quiz (QTI), weekly
challenge (QTI MCQ subset + interactive HTML), slides PPTX, and
infographic. Targets Common Cartridge 1.1 with QTI 1.2 — Canvas's
best-tested import profile.

Lossy conversions (assertion-reason, agreement-matrix, slider-estimation
question types) are skipped from QTI; the rich HTML version ships
alongside as a webcontent resource so the original interaction is still
available inside Canvas.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Bypasses the LLM pipeline so the Common Cartridge exporter can be
exercised without an Anthropic API key. The fixture covers every IMSCC
code path: HTML reading, practice quiz markdown, in-class quiz with
distractors, weekly challenge across all question types (including the
non-MCQ types that get skipped from QTI), slides JSON, and a tiny base64
JPEG infographic.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…es DOCX

Canvas's Page sanitizer strips inline scripts on import, which left the
rich practice-quiz and weekly-challenge single-page apps as dead markup.
Removing them from the cartridge entirely — the QTI versions cover the
gradeable use case, and the standalone "Publish Course" HTML viewer is
the right home for the interactive UX.

Teaching resources (discussions + activities) now ride along as a per-
chapter DOCX file resource, mirroring the existing per-chapter download.
Extracted the docx builder out of ExportPage into its own service module
so both call sites share it.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Each chapter's discussion prompts now become first-class IMS Discussion
Topic 1.1 resources (one XML per prompt) instead of only living in the
teaching-resources DOCX. Canvas imports them as native Discussions, so
students can actually reply rather than read a Word doc.

Activities still ride along in the DOCX — Canvas has no native primitive
for multi-step activity guides with facilitation tips and debriefs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…us body

Canvas reads a proprietary course_settings/course_settings.xml block
during CC import to populate course-level fields. Adding it routes the
syllabus.courseOverview into the Syllabus tab's body — which is visible
to enrolled students, unlike the IMS LOM <description> in the manifest
which only surfaces in Course Details.

Resources flagged as 'settings' are added to the manifest <resources>
list but intentionally omitted from the <organizations> tree, since
they're LMS configuration rather than module content.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…nized

Inline <syllabus_body> in course_settings.xml didn't take effect on
Canvas import — the syllabus tab still showed the empty-state stub.
Switching to Canvas's own export shape: separate course_settings/
syllabus.html file, course_settings.xml without the inline body, and
the resource href pointed at canvas_export.txt (the sentinel) rather
than course_settings.xml.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 7, 2026

Someone is attempting to deploy a commit to the JTprojects Team on Vercel.

A member of the Team first needs to authorize it.

daTechGuy pushed a commit to daTechGuy/CanvasClassBuild that referenced this pull request May 9, 2026
main now contains all CanvasClassBuild fork work — Canvas template
upload, IMSCC export (template-aware + non-template), Ollama Cloud
LLM provider, Tavily / Wikipedia research backends, course-outline
DOCX parsing, advanced-mode toggle, Canvas auto-publish sidecars,
and the rebrand. The 'main is upstream-aligned with a pointer'
phase ends here; visitors landing on the repo home now see the
fork's full README and code.

The imscc-canvas-only branch is unchanged and still scoped to the
upstream PR (jtangen#2).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant