🎓 The Academic Knowledge Management Dilemma
Modern higher education and enterprise training institutions rely almost universally on Learning Management Systems (LMS) like Instructure Canvas to distribute course syllabi, lecture modules, assignments, student discussions, and grading rubrics.
Yet for technical students, researchers, and security practitioners who build their intellectual workflows inside personal knowledge management (PKM) systems like Obsidian, Canvas represents an isolated, walled-off data silo:
- Ephemerality & Term Expiration: Once an academic semester concludes, student access to Canvas courses is routinely archived or revoked. Syllabi, instructor annotations, curated reading lists, and assignment rubrics vanish behind institutional access gates.
- Disconnected Knowledge Graphs: Course notes authored in Obsidian remain disconnected from source materials, grading criteria, and module pacing guides living inside the web browser.
-
Administrative Token Gating: Canvas exposes an extensive REST API, but institutional administrators frequently disable personal access tokens (
Account > Settings > + New Access Token) for student roles due to enterprise compliance policies. - Third-Party Cloud Aggregation Risks: Traditional third-party scrapers and web integrations require routing student session credentials, course documents, and peer discussions through external SaaS servers. For students handling proprietary lab code or education records governed by FERPA and GDPR, third-party cloud aggregation is an unacceptable privacy compromise.
Third-Party Cloud Scraper (High Risk):
[Canvas LMS] ----(Credentials/Course Data)----> [Cloud Relay / SaaS] ----> [Obsidian Vault]
▲
└── Attack Surface & Data Leakage Risk
Canvas Sync Bridge v0.4.0 (Hybrid Local-First Architecture):
[Canvas LMS REST API] ════(Direct Token / requestUrl)═══════════════════╗
▼
[Canvas LMS Web Tab] ════(Session Cookies)════> [Browser Ext] ──(127.0.0.1)──> [Obsidian Vault]
To eliminate this friction while upholding strict privacy boundaries and supply-chain integrity, I architected and open-sourced Canvas Sync Bridge v0.4.0—a production-grade, hybrid local-first ecosystem split into two dedicated, decoupled open-source GitHub repositories and audited against official Obsidian Community guidelines.
📦 Architectural Decoupling: Two Repositories, Two Independent Lifecycles
A central engineering milestone of the v0.4.0 release is the clean decoupling of the codebase into two standalone, single-responsibility open-source repositories:
┌─────────────────────────────────────────────────────────┐
│ CANVAS TO OBSIDIAN SUITE │
└────────────────────────────┬────────────────────────────┘
│
┌──────────────────────────────┴──────────────────────────────┐
│ │
▼ ▼
┌───────────────────────────────────────────────────────────┐ ┌───────────────────────────────────────────────────────────┐
│ OBSIDIAN DESKTOP & MOBILE PLUGIN │ │ COMPANION BROWSER WEBEXTENSION │
│ (https://github.com/SixFiveMil/obsidian-canvas-sync) │ │ (https://github.com/SixFiveMil/canvas-to-obsidian-extension)│
├───────────────────────────────────────────────────────────┤ ├───────────────────────────────────────────────────────────┤
│ • Native Obsidian requestUrl Direct REST API Client │ │ • Manifest V3 Service Worker (Chrome, Brave, Edge, Arc) │
│ • Vault Note Synthesizer & GFM Markdown Converter │ │ • WebExtensions API Packaging (Mozilla Firefox AMO) │
│ • Obsidian Community Directory CI (obsidian-workflows) │ │ • Zero-Token Session Extraction from active Canvas tabs │
│ • Popout Window & Mobile Scoping (Platform.isDesktop) │ │ • Automated Store Deployment Pipeline (publish-stores.mjs)│
│ • Cryptographically signed releases with SLSA Provenance │ │ • Link-local Loopback HTTP Dispatch (127.0.0.1:27125) │
└───────────────────────────────────────────────────────────┘ └───────────────────────────────────────────────────────────┘
Why Decouple into Separate Repositories?
- Independent Release Lifecycles & Store Governance: The Obsidian plugin and browser extensions target completely different distribution registries with different review timelines. The plugin is submitted to the Obsidian Community Plugins Directory and BRAT, whereas the extension targets the Chrome Web Store and Firefox Add-ons (AMO). Decoupling ensures that a patch to the Chrome MV3 background worker doesn't trigger unnecessary plugin releases or invalidate Obsidian community reviewer hashes.
-
Targeted CI/CD & Validation Pipelines:
The Obsidian plugin uses the official
obsidianmd/obsidian-workflowsaction witheslint-plugin-obsidianmdandstylelint. The browser extension repository uses web-extension manifest validators, Chrome Web Store API deployers, and AMO signing scripts. - Zero Dependency Bloat: Users who rely exclusively on the Direct REST API within Obsidian can install the plugin without downloading any browser extension build artifacts, while extension contributors don't need Obsidian Desktop API dependencies.
🏛️ Hybrid Ingestion Architecture
The decoupled ecosystem supports two complementary ingestion pathways that converge into a unified canonical note generator:
┌────────────────────────────────────────────────────────────────────────────────────────┐
│ CANVAS LMS CLOUD │
│ ┌────────────────────────────────────────────────────────────────────────────────┐ │
│ │ Canvas REST API (/api/v1/...) │ │
│ │ - Courses, Modules, Pages, Syllabus │ │
│ │ - Assignments, Rubrics & Student Submissions │ │
│ │ - Discussions & Complete Nested Reply Trees │ │
│ │ - Calendar Events & Due Date Milestones │ │
│ │ - Course Files & Static Asset Downloads │ │
│ └────────────────────────┬───────────────────────────────┬───────────────────────┘ │
└────────────────────────────┼───────────────────────────────┼───────────────────────────┘
│ │
Mode A: Direct API │ HTTPS │ Mode B: Session-Based
(Obsidian requestUrl) │ (Bearer Token) │ (Browser Session Cookies)
│ ▼
│ ┌───────────────────────────┐
│ │ Companion Web Extension │
│ │ (Chrome / Firefox MV3) │
│ │ - Session Extractor │
│ │ - Extraction Toggles │
│ └─────────────┬─────────────┘
│ │ Loopback POST (127.0.0.1:27125)
│ │ (Opt-in / Platform.isDesktop)
▼ ▼
┌────────────────────────────────────────────────────────────────────────────────────────┐
│ OBSIDIAN PLUGIN RUNTIME │
│ ┌─────────────────────────┐ ┌──────────────────────────────────┐ │
│ │ CanvasApiClient │ │ Loopback Bridge Server │ │
│ │ (Direct API Connection) │ │ (conditionally active) │ │
│ └────────────┬────────────┘ └────────────────┬─────────────────┘ │
│ │ │ │
│ └─────────────────────┬─────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────┐ │
│ │ Canonical Course Payload│ │
│ │ (CanvasCoursePayload) │ │
│ └─────────────┬─────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────┐ │
│ │ Markdown & Link Engine │ │
│ │ - GFM Converter (Turndown)│ │
│ │ - Wikilink Transformer │ │
│ │ - Table Pipe Escaper │ │
│ └─────────────┬─────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────┐ │
│ │ Asset & File Downloader │ │
│ │ - Binary Streamer │ │
│ │ - Size/Extension Filters │ │
│ └─────────────┬─────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────┐ │
│ │ Vault Note Generator │ │
│ │ - Path Sanitization │ │
│ │ - Templated Course Vault │ │
│ └─────────────┬─────────────┘ │
└─────────────────────────────────────┼──────────────────────────────────────────────────┘
▼
┌────────────────────────────────────────────────────────────────────────────────────────┐
│ OBSIDIAN VAULT STORAGE │
│ └── Canvas/CS510 - Network Security/ │
│ ├── Course.md, Home.md, Syllabus.md, Grades.md │
│ ├── Tasks.md, Discussions.md, Calendar.md │
│ ├── Modules/01 - Week 1/01 - Page - Lecture.md │
│ ├── Files/ (PDF, DOCX, XLSX, etc.) │
│ └── Attachments/ (Images, Banners) │
└────────────────────────────────────────────────────────────────────────────────────────┘
Ingestion Pathways Compared
| Ingestion Mode | Repository / Component | Ingestion Mechanism | Best For | Platform Support |
|---|---|---|---|---|
| Mode A: Direct REST API | obsidian-canvas-sync |
Native requestUrl adapter using personal Canvas API tokens |
Standard users, automated multi-course batch syncing, historical term archiving | Obsidian Desktop & Mobile |
| Mode B: Companion Web Extension | canvas-to-obsidian-extension |
Manifest V3 service worker extracting active tab session cookies | Locked-down universities where student API keys are disabled | Chrome, Firefox, Edge, Brave, Arc |
🛡️ Obsidian Community Compliance & Guidelines Hardening
To ensure enterprise-grade stability and prepare for official listing in the Obsidian Community Plugins directory, the plugin was audited and re-engineered against the complete suite of Obsidian developer guidelines:
1. Official CI/CD Validation Workflows
The plugin repository integrates the official obsidianmd/obsidian-workflows GitHub Action on all pull requests and tagged releases. Every commit is validated against:
-
eslint-plugin-obsidianmd: Enforcing plugin lifecycle contracts and DOM safety. -
stylelint: Ensuring theme neutrality and valid CSS custom properties. - Dynamic guideline guard tests asserting zero forbidden global overrides.
2. Multi-Window Popout Safety
In modern Obsidian releases (v1.0+), notes and modals can be dragged into detached, popout operating system windows. The plugin eliminates legacy globalThis and root document references, binding event listeners and DOM elements dynamically to context-aware activeWindow and window scopes.
3. Declarative Settings Search (getSettingDefinitions)
Canvas Sync Bridge implements getSettingDefinitions(), allowing users on Obsidian 1.13+ to search and jump directly to specific plugin settings (e.g. Canvas Base URL, Bridge Port, Asset Filter Allowlist) from the global Obsidian settings filter.
4. Dynamic Desktop Isolation (Platform.isDesktop)
Node.js core modules (http, url, path) required for the local loopback server are dynamically resolved and guarded behind Platform.isDesktop. This guarantees that the plugin initializes cleanly on Obsidian Mobile (iOS and Android) in Direct REST API mode without throwing module resolution faults.
5. Supply Chain Security & SLSA Build Provenance
Every release artifact (main.js, manifest.json, styles.css) is cryptographically signed and attested using SLSA build provenance predicates via GitHub OIDC and Sigstore. Build pipelines strictly prune non-essential assets, ensuring transparent, tamper-proof releases.
📊 Comprehensive Coursework Synchronization
Both ingestion modes stream course data into a canonical payload schema (CanvasCoursePayload), producing complete, interconnected vaults:
1. Grades & Submissions (Grades.md)
Syncs active grade standing, current course scores, submission status (Submitted, Graded, Missing), points earned vs points possible, submitted file links, and instructor feedback comments.
### 📊 Student Gradebook Summary
| Assignment | Status | Score | Max Points | Feedback |
| :--- | :--- | :--- | :--- | :--- |
| **Lab 1: Cryptanalysis** | Graded | 95.0 | 100.0 | Great implementation of Kasiski examination. |
| **Midterm Exam** | Graded | 88.0 | 90.0 | Solid analysis on forward secrecy. |
2. Discussions with Nested Reply Trees (Discussions.md)
Preserves instructor discussion prompts along with complete multi-tier nested student replies, formatted as hierarchical callouts with author timestamps and direct link anchors.
3. Assignments & Rubric Table Normalization (Tasks.md)
Canvas rubrics use complex, nested HTML tables. The engine converts these into clean GitHub Flavored Markdown (GFM) tables, capturing rating descriptions, point distributions, and grading criteria:
### 📋 Assignment Grading Rubric
| Criterion | Ratings | Max Points |
| :--- | :--- | :--- |
| **Architecture & Threat Model** | • Exemplary (20 pts): STRIDE model applied.<br>• Proficient (15 pts): Minor gaps.<br>• Novice (5 pts): Missing loopback controls. | 20 pts |
| **Unit Test Coverage** | • Full Marks (30 pts): 100% Vitest pass rate.<br>• Partial (20 pts): Missing edge cases. | 30 pts |
4. Local File & Asset Downloader (Files/ & Attachments/)
Directly downloads referenced course documents (.pdf, .docx, .pptx, .xlsx, .zip) and embedded images into dedicated vault folders. Includes configurable maximum file size limits (default: 50MB) and extension allowlists.
5. Wikilink Engine with Table Pipe Escaping
All internal module items and syllabus links are resolved to Obsidian [[wikilinks]]. Table-embedded links use strict pipe escaping ([[path\|alias]]) to ensure markdown tables render without broken column boundaries.
🗂️ Generated Vault Structure
Synced courses generate a structured, navigable directory hierarchy:
Canvas/
└── CS510 - Advanced Network Security/
├── Course.md # Master index note with metadata & instructor contact
├── Home.md # Course landing page & announcement banners
├── Syllabus.md # Complete syllabus text, policies & textbook list
├── Tasks.md # Assignment checklists, due dates & rubric tables
├── Grades.md # Gradebook table with scores, percentages & feedback
├── Discussions.md # Discussion board topics with full student reply trees
├── Calendar.md # Course milestones, due dates & Zoom meeting links
├── Modules/
│ ├── 01 - Week 1 - Applied Cryptography/
│ │ ├── 01 - Page - Stream Ciphers & Block Ciphers.md
│ │ └── 02 - Assignment - Breaking Polyalphabetic Ciphers.md
│ └── 02 - Week 2 - Protocol Vulnerabilities/
│ ├── 01 - Page - TLS 1.3 & Forward Secrecy.md
│ └── 02 - Assignment - Wireshark Decryption Lab.md
├── Files/ # Downloaded PDFs, DOCX, slides, spreadsheets, and archives
└── Attachments/ # Embedded images, course banners, and diagrams
🚀 Installation & Getting Started
1. Install the Obsidian Plugin
Method A: Community Plugins (Recommended)
- Open Obsidian Settings > Community Plugins.
- Disable Restricted mode if prompted.
- Search for Canvas Sync Bridge, click Install, and Enable.
Method B: Obsidian BRAT (Beta Builds)
- Install the BRAT Plugin in Obsidian.
- Under BRAT settings, click Add Beta plugin and enter:
https://github.com/SixFiveMil/obsidian-canvas-sync
Method C: Manual Release
Download main.js, manifest.json, and styles.css from the Latest GitHub Release and place them in <Vault>/.obsidian/plugins/canvas-sync-bridge/.
2. Choose Your Sync Method
Option A: Direct REST API (Recommended)
- In Canvas, navigate to Account > Settings > Approved Integrations > + New Access Token.
- Copy your generated access token.
- In Obsidian Settings under Canvas Sync, enter your Canvas Base URL (
https://canvas.instructure.comor your institution domain) and API Token. - Press
Ctrl/Cmd + Pand runCanvas Sync: Select & sync courses(or click the🎓ribbon icon) to launch the interactive course selector.
Option B: Browser Extension Bridge (Zero-Token Mode)
- In Obsidian Settings under Canvas Sync, toggle on Enable browser bridge listener.
- Install the companion extension:
- 🌐 Chrome Web Store (Chrome, Edge, Brave, Arc, Opera)
- 🦊 Firefox Add-ons (Mozilla)
- 📦 Extension Source Repo
- Open any Canvas course tab in your browser, click the extension icon, test the bridge connection, and click Sync Active Course.
🤝 Open Source & Community RFC
Canvas Sync Bridge and its companion extension are distributed under the MIT License across two dedicated open-source repositories:
- 💎 Obsidian Plugin: SixFiveMil/obsidian-canvas-sync
- 🌐 Browser Extension: SixFiveMil/canvas-to-obsidian-extension
We welcome feedback, issues, and contributions from students, researchers, and educators. Join the architectural discussion on GitHub Discussions!
Top comments (0)