[Proposal] Dark theme for Open edX platform
Overview
Introduce a system-wide dark theme across the Open edX Learner, Studio, and Instructor experiences, with automatic OS-preference detection and a manual toggle persisted to the user's profile. The theme would apply consistently across all MFEs, excluding legacy (non-MFE) functionality.
Problem
Learners and course authors frequently spend several hours per session on the platform, and the current light-only interface causes eye strain in low-light environments and clashes with the dark themes most users have already configured at the OS or browser level. The lack of a dark theme also makes Open edX feel dated compared to peer platforms, affecting perceived product quality.
Current State
Tutor Indigo and Its Limitations
A dark theme already exists in the Open edX ecosystem via the Tutor Indigo plugin, the default theme shipped with Tutor and maintained by Edly. The theme toggle button is enabled by default when Tutor Indigo is installed, and the theme can be switched from light to dark and vice versa. This is a meaningful step forward, but Indigo was not designed as a platform-level theming capability and has structural limitations that make it unsuitable as the long-term answer for Open edX platform.
Why this matters for the proposal. Indigo is best understood as a downstream theme plugin, not as the theming layer of the platform. A platform-level solution (this proposal) treats dark mode as a capability of Paragon and the MFEs themselves, so that:
Every MFE – including Authn, ORA, Authoring, Gradebook, and Communications – picks up dark mode through the shared Paragon design tokens. Components that already consume tokens adapt without per-MFE work; the bulk of the migration cost is a one-time replacement of remaining hardcoded color values with token references.
The theme preference is stored on the user, not the browser, and follows them across devices.
Operators inherit a working dark theme without taking on the maintenance burden of a custom Indigo fork, a custom
@edx/brandpackage, or a custom Tutor theme plugin.Tutor Indigo can then be re-based on the platform tokens and focus on what it does well – branding and visual identity – rather than re-implementing dark mode for each MFE it touches.
Indigo proves dark theme is demand and that the rough approach works; this proposal addresses the structural limitations that prevent Indigo from being a complete answer.
Cross-surface context: mobile is already there.
The official Open edX Android and iOS apps already ship dark mode, and in community already exist a Paragon-based design-tokens proposal for mobile branding and theming that derives the dark palette from shared tokens: [Proposal] Design Tokens for Open edX Mobile (Branding, Theming & Dark Mode). This creates two relevant facts for the web proposal.
First, a learner who uses both surfaces today gets an inconsistent experience – dark on mobile, light-only on the web – which the platform's own issue tracker already reflects (e.g.
Mobile apps unit screens flash from light to dark background · Issue #36222 · openedx/openedx-platform , where unit screens flash from light to dark inside the mobile app because the embedded web content isn't theme-aware).
Second, the proposed architecture here – Paragon design tokens as the single source of truth, dark palette defined alongside light, runtime switching – is the natural web-side counterpart of the mobile tokens proposal. Funding both together yields a single, coherent theming layer across the Open edX ecosystem rather than two parallel implementations.
Use Cases
User Story 1 — User theme preference | |
|---|---|
User Story | Acceptance Criteria |
As a user, |
|
User Story 2 — Platform-level theme switching control | |
|---|---|
User Story | Acceptance Criteria |
As a platform admin, |
|
Implementation Plan
Design definition and token mapping. Producing a complete, reviewable definition of the dark theme: palette, token mapping, and component-level behavior.
Design tokens as a foundation. Using the Paragon design tokens as the single source of truth for color, elevation, and border values across all MFEs. The theming tokens are defined twice – once for the light theme, once for the dark theme – and shipped as separate variant stylesheets (
light.css,dark.css) that Paragon swaps at runtime viauseParagonThemeinfrontend-platform, driven by URLs supplied through the MFE Config API.Theme controller and persistence. Extend the existing Paragon theme manager in
frontend-platform(AppProvider,useParagonTheme,setThemeVariant) rather than introducing a new module. The new pieces this proposal adds are:a user-preference resolution step that reads the value from the account API and feeds it into
setThemeVariant;a
localStoragefallback so pre-auth visitors and anonymous learners get a consistent theme across reloads;the resulting resolution order – authenticated user preference →
localStorage→prefers-color-schememedia query → light;the user-facing account-menu control with three options: Light, Dark, System default (the default for new users).
Persistence uses the existing user preferences endpoint (/api/user/v1/preferences/{username}) with a new pref-theme key (allowed values: light | dark | system), so the choice follows the user across devices. Because the authenticated preference arrives asynchronously after sign-in, applying it only inside React would cause a flash of incorrect theme on first paint – the same FOUC issue the mobile-tokens proposal cites for native apps, which applies to the web equally. An inline pre-paint script in the document head reads localStorage (falling back to prefers-color-scheme) and sets the active variant before the first render; React then reconciles to the authenticated preference once it loads.
Surface coverage, phased. Rolling out everywhere at once is high-risk; instead the work is sequenced by user impact and technical readiness:
Phase 1 – Learning experience: Learning MFE, Profile, Account, Authentication, header/footer. These already consume Paragon heavily and give immediate value to learners.
Phase 2 – Authoring & instructor tools: Course Authoring MFE, Gradebook MFE, ORA, Discussions MFE.
Phase 3 — Long tail (best-effort): Embedded XBlocks, the rich-text editor (TinyMCE skin), code editors (CodeMirror/Monaco themes). These run in isolated DOM (iframes, shadow DOM) or use their own theming APIs and so don't inherit Paragon tokens through the CSS cascade. Each requires a dedicated dark-theme mapping built against the same source palette, with a documented fallback (default: light rendering) for any sub-surface that doesn't have a dark mapping yet.
Each phase ships behind a per-site rollout toggle so operators can opt in during stabilization: a Django waffle flag dark_theme.enabled for legacy LMS/Studio surfaces, mirrored to MFEs through the MFE Config API (e.g., ENABLE_DARK_THEME) since MFEs cannot read Django waffle flags directly. Both halves read the same per-site source of truth and stay in sync.
Long-Term Ownership and Maintenance
Day-to-day maintenance is handled by the maintainers of the repositories where any changes are added – the same model Open edX uses for the rest of the platform. To keep dark mode from eroding silently as the platform evolves, this proposal funds four guardrails:
Visual-regression coverage in both variants. Automated visual diffs on every PR in both light and dark themes; reuses Paragon's existing visual-diff pipeline rather than introducing a parallel one.
Automated WCAG AA contrast check. axe-core (or equivalent) CI step verifying every paired token and component meets WCAG AA in both themes, running on every PR to Paragon and participating MFEs.
"Tokens only, no hardcoded colors" lint rule. Stylelint rule blocking new hex /
rgb()values in component CSS at PR time, with a documented escape hatch – prevents the hardcoded-color problem from re-emerging after the initial migration.
Named sponsoring working group. Paragon WG as primary owner; Accessibility WG as standing reviewer for contrast tooling and future high-contrast variant.
Funding the guardrails is what keeps dark mode functional in year two and beyond – without them, dark coverage drifts as MFEs evolve, contrast quietly regresses, and the per-MFE migration work has to be re-done.
Contact
@Anastasiia Abyzova
Supporting Data
Raccoon Gang customer demand. Raccoon Gang has receiving a significant and recurring volume of customer requests for a dark theme across its Open edX engagements. To meet that demand, the company has already shipped a working dark theme inside the existing Open edX ecosystem – proving feasibility and validating user appetite – but the current implementation inherits the structural limitations described in Current State: Tutor Indigo and Its Limitations (partial MFE coverage, iframe and embedded-content gaps, browser-local persistence, no first-class platform integration). This proposal is the natural next step: graduate dark mode from a per-customer customization into a platform-level capability that Raccoon Gang and the wider community can rely on without re-solving the same problems on every project.
Community signal. Ongoing discussions and enhancement issues on the Tutor Indigo repository (e.g.
Indigo Dark Theme Enhancements · Issue #116 · overhangio/tutor-indigo ) and on the Open edX forum demonstrate that the gaps in existing dark-mode coverage – Authn, Course Authoring, Gradebook, ORA, Communications, embedded discussion sidebar, Image Explorer – are widely felt across the community, not specific to one operator.Industry baseline. Most major LMS and content platforms (YouTube, Notion, GitHub, VS Code, Coursera mobile) now ship dark mode as standard. Its absence in core Open edX platform is increasingly flagged in usability reviews and prospect conversations.
Accessibility. Dark themes benefit users with photophobia, migraine sensitivity, and certain visual impairments. Pairing the launch with a WCAG AA contrast audit strengthens the platform's accessibility posture and reuses the same token infrastructure for a future high-contrast theme.
Competitive Research. Existing Raccoon Gang dark-theme implementations.
n8n Academy
Gymsec