Skip to content

0006 — Learning Management: Self-Hosted Moodle, Integrated with the Member Portal

  • Status: Accepted
  • Date: 2026-05-09 (revised from earlier TutorLMS draft)
  • Decision owners: Gina Lyn Cox · Operations Lead
  • Related: ADR-004 (Forms Permissions) · ADR-005 (BuddyBoss Platform) · ADR-007 (Library & Video Hosting) · ADR-008 (Guild ↔ Ganjier Brand Relationship) · guildcommerce-core-plugin

Context

The Guild needs an LMS to deliver cert-bearing courses, quizzes, certifications, and CE-hour tracking. The LMS must integrate with the member portal — single sign-on, shared brand, shared permission model — so members experience one product, not two.

The Guild operates under a brand license with the Ganjier program (handled by counsel, see ADR-008) but is structurally independent. The Guild does not own Ganjier-program educational content and will not migrate it. The Guild's LMS launches empty and is populated only with Guild-original content.

Cert-bearing content (courses that issue certifications, track CE hours, or validate credentials) must live in a real LMS with a quiz/exam engine, completion tracking, gradebook, and certificate issuance. Non-cert content (Guild Hour replays, resource documents, casual videos) does not need any of that — it just needs to be browseable, searchable, and permission-gated. ADR-007 covers the non-cert side.

Decision

Adopt self-hosted Moodle as the Guild's LMS, served at learn.ganjierguild.com, co-located on the existing Cloudways droplet alongside the WordPress member portal. Themed with Boost Union to match the Guild brand. Integrated with the WordPress portal via:

  • Single sign-on — auth_oidc Moodle plugin pairs with an OIDC bridge in guildcommerce-core-plugin. Members logged into the portal land authenticated in Moodle without a second login.
  • Theme parity — Boost Union (free Moodle theme) loads custom CSS that mirrors guildcommerce-theme color tokens, fonts, and visual rhythm. Visually, members shouldn't notice a system change.
  • Profile widget — lms-bridge module in guildcommerce-core-plugin adds a "My Learning" tab to BuddyBoss profiles showing enrolled courses, progress %, certificates earned, and CE hours total. Data fetched from Moodle's REST API, cached in WordPress.
  • Completion sync — Moodle webhooks fire on course completion. lms-bridge writes a row to the ce-ledger module capturing course ID, hours, completion date, member ID. CE hours are then visible in the member's profile and used for credentialing reviews.
  • Certificates — mod_customcert (free Moodle plugin) issues branded PDF certificates on completion. Certificate URLs sync to WordPress for profile display and download.

The certificate issuance flow uses Moodle's native PDF generation. No Credly, no Accredible. Native PDFs are sufficient for Year 1.

Architecture

                    Member's browser
                          │
              ┌───────────┴───────────┐
              │                       │
              ▼                       ▼
   ganjierguild.com          learn.ganjierguild.com
   (WordPress + BuddyBoss     (Moodle + Boost Union theme +
    + guildcommerce-theme +    auth_oidc + mod_customcert)
    guildcommerce-core-plugin)
              │                       ▲
              │                       │
              │   OIDC SSO bridge     │
              ├──────────────────────►│
              │                       │
              │   REST API (course    │
              │   catalog, progress,  │
              │   enrollment)         │
              │◄──────────────────────┤
              │                       │
              │   Webhook on          │
              │   course completion   │
              │◄──────────────────────┤
              │                       │
              ▼                       │
   guildcommerce-core-plugin          │
   ├── lms-bridge/                    │
   │   ├── sso-handler.php  ──────────┘
   │   ├── api-client.php
   │   ├── webhook-receiver.php
   │   └── profile-tab.php
   ├── ce-ledger/
   │   └── (writes CE hour records on completion)
   └── library/  (ADR-007 — non-cert replays + resources)

Both domains are deployed on the Guild's existing Cloudways Autonomous environment. Moodle runs as a separate application with its own database; WordPress runs as the primary application. The two share the same managed Cloudways environment but are otherwise isolated at the application layer.

Hosting decision

Deploy Moodle alongside WordPress on the Guild's existing Cloudways Autonomous environment — $0 incremental cost.

Cloudways Autonomous handles traffic scaling and resource allocation at the platform level. Resource pressure from one application does not starve the other in the way a fixed-size droplet would, and adding a second application doesn't require capacity planning the way a managed VPS would.

Justification:

  • $0 incremental software, hosting, or scaling cost
  • Cloudways Autonomous handles resource scaling automatically; no manual droplet sizing needed
  • One managed environment to back up, patch, and monitor
  • Subdomain DNS already terminates at Cloudways; adding learn.ganjierguild.com is a configuration change, not new infrastructure
  • Application-layer isolation (separate database, separate filesystem path, separate Cloudways app) keeps Moodle and WordPress operationally independent
  • SSL, backups, security patching all unified under Cloudways' managed tier

Why self-hosted Moodle

Goal Self-hosted Moodle Open LMS LearnDash TutorLMS in WP
Best-in-class quiz/exam tooling Yes Yes (same Moodle core) Strong Strong
Question banks, randomization, time limits, multiple attempts Native Native Yes Yes (free tier)
Cohort-based enrollment Native Native Add-on Yes
Familiar to founders (Ganjier program uses Moodle) Yes Yes No No
Cost (Year 1) $0 $5K–$20K+/yr $199/yr $0
Open-source, owned data Yes No (vendor lock) No (vendor) No (vendor)
Native PDF certificates (no per-badge fees) Yes (mod_customcert) Yes Paid add-on Free add-on
Hosting cost $0 (co-located) Bundled $0 $0
Same software family as the Ganjier program Yes Yes No No
Operational complexity Two systems integrated Two systems integrated One system One system

The deciding factor is Moodle's quiz/exam engine combined with $0 cost. For a credentialing-oriented society, the quiz/exam tooling is the single most important LMS feature, and Moodle leads the field. Open LMS is the same software with a paid wrapper we don't need. LearnDash and TutorLMS are capable but not at Moodle's level for psychometric-grade exam workflows the Guild may eventually adopt.

The two-systems integration burden is real but bounded: SSO + REST API + webhook is well-trodden territory, and Boost Union solves theme parity for free.

Why no Credly / Accredible

Native Moodle certificates (via mod_customcert) are sufficient for Year 1. Credly and Accredible cost per badge issued (~$1–$5 each) plus a base fee, and exist primarily to provide portable Open Badge 2.0/3.0 credentials. The Guild's certifications are internally verifiable through the member directory + the issued PDF. If a regulator or accreditor later requires Open Badge issuance, we revisit.

Why no content migration

The Guild and the Ganjier program are independent (ADR-008). The Ganjier program's existing Open LMS install is not the Guild's to migrate from. The Guild has no claim on Ganjier-program courses, quiz banks, instructor materials, or member progress data under the current license scope.

This means:

  • No .mbz exports from the Ganjier program's Moodle to the Guild's Moodle
  • No course rebuilding from Ganjier materials even paraphrased
  • No co-branded courses unless the brand license is amended to cover content delivery (would require ADR amendment)
  • Existing Ganjier credential holders remain valid — those credentials are issued by the Ganjier program, not the Guild, and remain unaffected

The Guild's Year 1 course roadmap is Guild-original content authored by the Education committee and Guild instructors. Likely categories: governance training for new board members, ethics CE, cannabis-industry business operations, advocacy training, member-portal-onboarding video tour.

Plugins

Moodle plugin Purpose Cost
Boost Union (theme) Brand parity with guildcommerce-theme; loads custom CSS $0
auth_oidc OIDC SSO from WordPress $0
mod_customcert Branded PDF certificate issuance $0
local_webhooks (or built-in event observer) Course completion webhook → WordPress $0

All Moodle plugins are free, open-source, and actively maintained.

Cost

Component Cost
Moodle software $0
Boost Union, auth_oidc, mod_customcert, webhook plugin $0
lms-bridge module in guildcommerce-core-plugin $0 (we own it)
ce-ledger module in guildcommerce-core-plugin $0 (we own it)
Hosting (Moodle as second app on existing Cloudways Autonomous environment) $0 incremental
Domain (learn.ganjierguild.com subdomain) $0 (same registration)
Total $0/mo

Cloudways Autonomous billing scales with actual resource use; adding Moodle as a second application does not introduce a fixed per-droplet line item the way a managed VPS would.

Consequences

Positive:

  • $0 ongoing software cost; same domain registration
  • Same software family as the Ganjier program — familiar to founders
  • Best-in-class quiz/exam tooling protects future credentialing workflows
  • Owned data, owned infrastructure, no vendor lock
  • CE ledger module gives the Guild a first-class, auditable credentialing record
  • Visual integration via theme parity makes the two systems feel like one product
  • Co-located hosting keeps costs at zero while traffic is light; clean escalation path when it isn't

Negative / risks:

  • Two systems to operate (Moodle + WordPress) versus one for plugin-based LMS
  • Sysadmin burden: Moodle security patches, plugin compatibility, backups
  • Theme parity requires ongoing maintenance — when guildcommerce-theme changes, Boost Union CSS needs matching updates
  • SSO bridge is custom code in guildcommerce-core-plugin; bugs there mean broken member experience
  • Two applications on one Cloudways environment means a Cloudways-level outage takes both down simultaneously (mitigated by Cloudways' managed redundancy)

Mitigations:

  • Cloudways managed hosting handles patching, backups, and SSL automatically
  • Boost Union CSS lives in the same repo as guildcommerce-theme; theme PRs include LMS theme parity checks
  • SSO bridge gets unit tests + smoke tests in CI; well-defined OIDC contract
  • Cloudways Autonomous handles resource scaling at the platform level, so co-deployment is operationally appropriate without a split trigger

When to revisit

  • Member volume + course volume justifies a hosted LMS contract (e.g., Open LMS) for support and SLA reasons
  • Regulatory or accreditation body requires Open Badge issuance, triggering Credly/Accredible reconsideration
  • The Ganjier-brand license is amended to allow Ganjier-program content delivery, requiring license-aware course-publishing controls
  • Cloudways tier change (downgrade to managed VPS) reintroduces fixed-capacity considerations
  • A future credentialing program needs proctored exams, requiring Moodle Workplace or a proctoring service add-on

Implementation

Step Owner Status
Provision learn.ganjierguild.com subdomain Sysadmin Pending
Add Moodle as a new application on existing Cloudways Autonomous environment Sysadmin Pending
Install + configure Boost Union theme matching guildcommerce-theme Full-stack dev Pending
Install auth_oidc, mod_customcert, completion-webhook plugins Sysadmin Pending
Build lms-bridge module in guildcommerce-core-plugin Full-stack dev Pending
Build ce-ledger module in guildcommerce-core-plugin Full-stack dev Pending
Build BuddyBoss profile "My Learning" tab Full-stack dev Pending
Define Year 1 Guild-original course roadmap Education chair + founding board Pending
Author first Guild-original course Education chair Pending
Update Form O matrix with course visibility rules Operations Lead Pending
Document operational workflows Operations Lead This commit (programs/learning/README.md)
Member-facing announcement Communications chair Pending
Verify Cloudways Autonomous monitoring + alerting covers both apps Sysadmin Pending