Skip to content

Repository files navigation

org-canvas

https://img.shields.io/badge/status-beta-yellow.svg https://img.shields.io/github/license/ransomts/org-canvas.svg https://github.com/ransomts/org-canvas/actions/workflows/ci.yml/badge.svg https://codecov.io/gh/ransomts/org-canvas/graph/badge.svg

Overview

org-canvas is an Emacs package that synchronizes course content from Org Mode files to Canvas LMS via its REST API. It enables a “source of truth” workflow where instructors design their entire course in Org Mode and push changes to Canvas.

Tested against the Canvas LMS REST API (/api/v1/) as of 2026-02-07. Canvas does not version its API beyond v1; see the Canvas API Change Log for recent changes.

Key Features

  • Org Mode as Source of Truth: Design your course in plain text with full Org Mode capabilities
  • Bidirectional Sync: Push content to Canvas and pull existing courses into Org files
  • Conflict Detection: Interactive push/pull/skip resolution when remote changes are detected
  • Modular Architecture: Sync individual content types or the entire course at once
  • Dependency-Aware: Syncs in proper order respecting cross-references between files
  • 16 Content Types: Assignments, classic quizzes, New Quizzes, pages, modules, rubrics, outcomes, discussions, announcements, files, assignment groups, group categories, sections, per-section date overrides, calendar events, and course settings
  • Submission Grading: View submissions, post comments, download attachments, and push grades back to Canvas – all from Emacs
  • Canvas Migration: Import an entire existing Canvas course into Org files with org-canvas-pull-all
  • Orphan Cleanup: Detect and remove Canvas items that no longer have corresponding Org headings
  • Resilient Syncing: Pre-sync credential validation, rate limit retry with backoff, actionable error messages for auth failures, graceful handling of missing files

Installation

org-canvas is not yet on MELPA. Install from source:

;; Using use-package with straight.el
(use-package org-canvas
  :straight (org-canvas :type git :host github :repo "ransomts/org-canvas"
                        :files ("lisp/*.el")))

;; Using use-package with built-in vc-package (Emacs 29+)
(use-package org-canvas
  :vc (:url "https://github.com/ransomts/org-canvas"))

The :files directive is not optional. The sources live in lisp/, and a symlink at the repository root points at lisp/org-canvas.el so that eldev lint can find the Package-Requires header where package-lint expects it. straight.el’s default directive matches both *.el and lisp/*.el, sees the same file twice, and warns:

Warning (straight): Attempted to link ".../build/org-canvas/org-canvas.el" to both
  ".../repos/org-canvas/org-canvas.el" and ".../repos/org-canvas/lisp/org-canvas.el"

Naming lisp/*.el resolves the ambiguity.

Or clone for development:

git clone https://github.com/ransomts/org-canvas.git
cd org-canvas
eldev prepare

Quick Start

Configuration

The easiest way to set up a new course is the setup wizard:

M-x org-canvas-init

This prompts for your Canvas URL, API token, and course ID, tests the connection, writes org-canvas-credentials.el, and optionally creates skeleton .org files for all content types.

Or create org-canvas-credentials.el manually in your course directory (not tracked by git):

(setq org-canvas-api-token "your-canvas-api-token")
(setq org-canvas-course-id "12345")
(setq org-canvas-base-url "https://canvas.instructure.com")
(setq org-canvas-directory "/path/to/your/course/")

Course Structure

Create Org files for each content type:

my-course/
├── org-canvas-credentials.el  ; Your API credentials (gitignored)
├── settings.org               ; Course settings (timezone, homepage, license, navigation tabs)
├── assignments.org            ; Course assignments
├── quizzes.org               ; Classic quizzes with questions
├── new-quizzes.org           ; New Quizzes (Canvas next-gen quiz engine)
├── pages.org                 ; Wiki pages
├── modules.org               ; Course structure/navigation
├── rubrics.org               ; Grading rubrics
├── outcomes.org              ; Learning outcomes
├── discussions.org           ; Discussion boards
├── announcements.org         ; Course announcements
├── files.org                 ; File uploads
├── assignment-groups.org     ; Grade weighting categories
├── group-categories.org      ; Group sets for group assignments/discussions
├── calendar.org              ; Calendar events (office hours, holidays, review sessions)
└── sections.org              ; Course sections (pulled from Canvas) & date overrides

Basic Usage

All commands are accessible through a transient menu:

;; Open the command menu (recommended — shows all commands with keybindings)
M-x org-canvas-dispatch

Or call commands directly:

;; Test your connection
M-x org-canvas-test-connection

;; See sync status overview
M-x org-canvas-status

;; Validate all org files (offline, no API calls)
M-x org-canvas-validate

;; Preview what would be synced (no API calls)
M-x org-canvas-sync-dry-run

;; Sync everything (respects dependencies, detects conflicts)
M-x org-canvas-sync

;; Force sync, overwriting any remote changes
M-x org-canvas-force-push

;; Sync individual content types
M-x org-canvas-sync-assignments
M-x org-canvas-sync-quizzes
M-x org-canvas-sync-new-quizzes
M-x org-canvas-sync-pages
M-x org-canvas-sync-settings
M-x org-canvas-sync-group-categories
M-x org-canvas-sync-calendar-events
;; ... etc for all 16 content types

;; Sync a single item at cursor
M-x org-canvas-sync-assignment-at-point

;; Import an existing Canvas course into Org files
M-x org-canvas-pull-all

;; Pull individual content types from Canvas
M-x org-canvas-pull-assignments
M-x org-canvas-pull-pages
;; ... etc for all content types

;; View, comment on, and grade submissions
M-x org-canvas-submissions-view

;; Find and remove orphaned Canvas items
M-x org-canvas-cleanup-orphans

;; Delete all content from Canvas
M-x org-canvas-delete-all

Example: Creating an Assignment

* Lab 1: Introduction to Python
:PROPERTIES:
:POINTS: 100
:DUE_AT: <2025-09-15 Mon 23:59>
:SUBMISSION: online_upload
:ALLOWED_EXTENSIONS: py
:GROUP: [[file:assignment-groups.org::*Labs][Labs]]
:RUBRIC_LINK: [[file:rubrics.org::*Standard Lab Rubric][Standard Lab Rubric]]
:END:

Write a Python program that prints "Hello, World!" and demonstrates
basic variable usage.

** Requirements
- Create a file named =hello.py=
- Print a greeting message
- Define at least one variable

After syncing, org-canvas automatically adds:

:CANVAS_ID: 123456
:LAST_SYNCED: [2025-02-02 Sun 10:30]

Viewing and Grading Submissions

org-canvas includes a submissions viewer for reviewing student work, posting comments, downloading attachments, and pushing grades – all without leaving Emacs.

M-x org-canvas-submissions-view

This prompts for an assignment, fetches submissions from Canvas, and opens an interactive buffer with keybindings:

KeyAction
vToggle between summary table and detail view
cPost a comment on the submission at point
dDownload submission attachments
SPush modified grades to Canvas
gRefresh submissions from Canvas
qQuit

In detail view, edit the :SCORE: property on any student heading and press S to push grade changes. org-canvas detects which scores changed and confirms before pushing.

Documentation

  • Reference Manual – Complete file format specs, all properties, command reference, architecture
  • Workflows Guide – Semester setup, weekly/daily/per-assignment workflows, grading, multi-instructor collaboration
  • FAQ & Recipes – Quick answers to “how do I…” questions for assignments, quizzes, modules, grading, and more
  • Quick Reference Card – All properties, commands, and keybindings on one page
  • Migration Guide – Switching from Canvas web UI to an Org Mode workflow
  • Pitfalls & Gotchas – Common mistakes and how to avoid them
  • Canvas Coverage Map – What org-canvas manages, what it only reads, and what in Canvas it never touches
  • Demo Course – Complete example course (DS 101) showcasing all content types
  • Contributing – Development setup, coding conventions, testing practices, PR process

Dependencies

  • Emacs 29.1+
  • Org Mode 9.6+
  • plz - HTTP library
  • elog - Logging framework
  • transient (0.4+) - Command menu (built into Emacs 29+)
  • pandoc (optional) - Required for HTML-to-Org conversion when pulling content from Canvas

Development

# Run tests
eldev test

# Run tests with coverage
eldev test -u "on,text,dontsend"

# Lint
eldev lint

# Compile
eldev compile

License

GPL3 License. See LICENSE for details.

About

Emacs package for synchronizing Org Mode course content to Canvas LMS via its REST API

Topics

Resources

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages