Skip to content

feat: develop brand-openedx locally with "tutor dev" + fix legacy MFE theme CSS URLs - #252

Merged
arbirali merged 6 commits into
releasefrom
rahat/local-brand-openedx-dev
Oct 8, 2026
Merged

arbirali merged 6 commits into
releasefrom
rahat/local-brand-openedx-dev

Conversation

@arbirali

@arbirali arbirali commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator

Description

This PR makes it possible to work on a local brand-openedx checkout and see style changes live in tutor dev, and fixes the theme CSS URLs used by the legacy MFEs.

1. Local brand-openedx development (feat)

Until now, the MFEs always loaded the theme CSS from the published brand-openedx repository, so style changes could only be tested after pushing them.

This adds a new INDIGO_BRAND_OPENEDX_PATH setting. When it is set, in development mode:

  • A new indigo-brand service builds the local brand-openedx checkout and serves its CSS at http://localhost:3000.
  • It rebuilds automatically when files change:
    • paragon/*.scss → rebuilds core.css only (~10 s)
    • paragon/tokens/** → rebuilds all CSS (~2 min)
    • dist/ is not deleted during rebuilds, so the previous CSS keeps being served.
  • All MFEs (legacy and frontend-base) load core.css, light.css and dark.css from the local service. This overrides the theme URLs set by other plugins, such as tutor-contrib-paragon.

If the path doesn't point to a brand-openedx checkout, tutor config save fails with a clear error message.

Production (tutor local, tutor k8s) is not affected: the settings are only rendered in the development LMS settings and the dev docker-compose file. When the setting is unset (the default), the rendered environment is unchanged.

New settings:

Setting Default
INDIGO_BRAND_OPENEDX_PATH ""
INDIGO_BRAND_OPENEDX_DEV_PORT 3000
INDIGO_BRAND_OPENEDX_DEV_DOCKER_IMAGE docker.io/node:22

2. Fix: legacy MFE theme CSS loaded from raw.githubusercontent.com (fix)

PARAGON_THEME_URLS, used by the legacy MFEs, pointed to raw.githubusercontent.com. That host serves files as text/plain with X-Content-Type-Options: nosniff, so browsers refuse to apply them as stylesheets. The legacy MFEs then silently fall back to the default Paragon theme. These URLs now use jsDelivr, which serves text/css, like the frontend-base theme URLs already do. Same repository, branch and files.

This is a separate commit, so it can be cherry-picked onto other branches.

Testing instructions

Local brand development

  1. Clone the brand repository and point Indigo to it:
   git clone <brand-openedx-repository-url> /path/to/brand-openedx
   tutor config save --set INDIGO_BRAND_OPENEDX_PATH=/path/to/brand-openedx
   tutor dev launch
  1. Run tutor dev logs -f indigo-brand and wait for the server to start. Then open http://localhost:3000/light.css; it should show CSS.
  2. Open an MFE. In the browser's Network tab, core.css, light.css and dark.css should load from localhost:3000.
  3. Edit paragon/_overrides.scss (for example body { outline: 5px solid red; }). After the rebuild, a hard refresh should show the change.
  4. Change color.primary.base in paragon/tokens/src/themes/light/color.json. After the full rebuild (~2 min), a hard refresh should show the new primary color.
  5. Run tutor config save --unset INDIGO_BRAND_OPENEDX_PATH && tutor dev launch. The CSS should load from jsDelivr again, and the indigo-brand service should not be running.
  6. Run tutor config save --set INDIGO_BRAND_OPENEDX_PATH=/nope. It should fail with a clear error message.
  7. With the path set, production.py should not contain any localhost:3000 URL.

Legacy MFE theme URLs

  1. Without INDIGO_BRAND_OPENEDX_PATH, open a legacy MFE (e.g. learning).
  2. light.min.css and dark.min.css should load from cdn.jsdelivr.net as text/css.
  3. There should be no "Refused to apply style … MIME type ('text/plain')" error in the console.

Notes

  • jsDelivr may cache branch URLs for up to ~12 hours. After pushing brand changes, the cache can be purged at https://purge.jsdelivr.net/gh/<owner>/<repo>@<branch>/dist/<file>.min.css.
  • The development builds update the dist/ and paragon/build/ folders of the local brand-openedx checkout.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GnPNrsTx73ShPB6Kc6FWac

arbirali and others added 2 commits October 5, 2026 17:00
raw.githubusercontent.com serves files as text/plain with
"X-Content-Type-Options: nosniff", so browsers refuse to apply them as
stylesheets and the legacy MFEs silently fall back to the default
Paragon theme. Use jsDelivr, which serves text/css, like the
frontend-base theme URLs already do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GnPNrsTx73ShPB6Kc6FWac
Add the INDIGO_BRAND_OPENEDX_PATH setting. When it is set, "tutor dev"
runs an "indigo-brand" service that builds the local brand-openedx
checkout, rebuilds it on change and serves its CSS on
INDIGO_BRAND_OPENEDX_DEV_PORT (3000 by default). In development, the
MFEs then load the theme CSS from there instead of jsDelivr.
Production is not affected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GnPNrsTx73ShPB6Kc6FWac
Fix the E501 errors reported by "make test-lint".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GnPNrsTx73ShPB6Kc6FWac
@arbirali arbirali self-assigned this Oct 5, 2026
@Faraz32123
Faraz32123 self-requested a review October 7, 2026 11:46

@Faraz32123 Faraz32123 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally with tutor dev against a brand-openedx checkout: SCSS edits (learning + learner dashboard) and design token changes both rebuild and show up in the MFEs. LGTM 👍

One small thing: the SCSS watcher only watches paragon/, but paragon/_dark.scss imports ../themes/dark/_utilities.scss and ../themes/dark/_extras.scss, so edits to the dark theme files don't trigger a rebuild. Adding --watch themes to the first nodemon call should fix it:

npx nodemon --legacy-watch --on-change-only --watch paragon --watch themes \\
  --ignore 'paragon/build/**' --ignore 'paragon/tokens/**' \\
  --ext scss,css --exec "$$CORE_BUILD" &

arbirali and others added 2 commits October 7, 2026 11:58
paragon/_dark.scss imports themes/dark/_utilities.scss and
themes/dark/_extras.scss, so also watch the themes/ folder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GnPNrsTx73ShPB6Kc6FWac
@arbirali

arbirali commented Oct 7, 2026

Copy link
Copy Markdown
Collaborator Author

Tested locally with tutor dev against a brand-openedx checkout: SCSS edits (learning + learner dashboard) and design token changes both rebuild and show up in the MFEs. LGTM 👍

One small thing: the SCSS watcher only watches paragon/, but paragon/_dark.scss imports ../themes/dark/_utilities.scss and ../themes/dark/_extras.scss, so edits to the dark theme files don't trigger a rebuild. Adding --watch themes to the first nodemon call should fix it:

npx nodemon --legacy-watch --on-change-only --watch paragon --watch themes \\
  --ignore 'paragon/build/**' --ignore 'paragon/tokens/**' \\
  --ext scss,css --exec "$$CORE_BUILD" &

Good catch, thanks! paragon/_dark.scss imports themes/dark/_utilities.scss and themes/dark/_extras.scss, so edits there weren't triggering a rebuild. Fixed in 72055b5: the SCSS watcher now also watches themes/, and the README mentions it. Checked that editing themes/dark/_extras.scss rebuilds core.css, and that brand forks without a themes/ folder still work.

@arbirali
arbirali requested a review from Faraz32123 October 7, 2026 12:12
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GnPNrsTx73ShPB6Kc6FWac
@arbirali
arbirali merged commit dde8da0 into release Oct 8, 2026
2 checks passed
@arbirali
arbirali deleted the rahat/local-brand-openedx-dev branch October 8, 2026 09:50
arbirali added a commit that referenced this pull request Oct 8, 2026
Resolve the conflicts with #252 by keeping this branch's version: no
@edx/brand npm install, and the theme CSS URLs built from
BRAND_CSS_BASE_URL with brandOverride only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GnPNrsTx73ShPB6Kc6FWac
arbirali added a commit that referenced this pull request Oct 8, 2026
indigo-3.1.1 fixes the position of the account menu in the mobile
header.

Also drop the changelog entry about the raw.githubusercontent.com URLs:
that fix was already shipped by #252, which has its own entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GnPNrsTx73ShPB6Kc6FWac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

2 participants