Skip to content

Fix frontend-base branding #232

@arbrandes

Description

@arbrandes

Description

Branding via @openedx/brand-openedx is not reliably applied in sites built on frontend-base. In frontend-site, only the body element picks up the brand's typography tokens on initial load; content inside lazy-loaded app routes reverts to Paragon's defaults. The cause is a CSS load-order fight that the current layering makes easy to hit.

frontend-base/shell/app.scss imports Paragon's core.min.css and light.min.css. The problem is that each consuming app has its own src/app.scss that begins with @use "@openedx/frontend-base/shell/app.scss", and that app.scss is imported from the app's Main module, which is itself code-split via import('./Main') in the app's router. Each of those imports is a separate Sass compilation unit. Sass @use dedupes within one compile, but not across compiles, so Paragon's stylesheet ends up bundled both into the site's main CSS and into each per-app lazy chunk.

At runtime, the site's main bundle loads first with Paragon followed by the brand overrides. When the user navigates to an app route, that app's chunk CSS is appended to <head> after the brand styles. Because CSS custom properties live on the element they target and var() resolves at use-time against the current computed value, the chunk's :root { --pgn-typography-font-family-sans-serif: ... } declaration clobbers the brand's value globally, for every consumer in the document.

The runtime-URL mechanism documented in docs/how_tos/theming.md (siteConfig.theme with core.url and variants.<name>.url) does not avoid this on its own, because the theme <link> is inserted on React mount and the lazy app chunks still append after it.

The fix is to stop apps from re-bundling the shell, and keep the site as the single owner of global styles. frontend-base itself stays brand-agnostic: Paragon remains in shell/app.scss because it is part of the shell's contract, but brand is the site's choice and should not be introduced into frontend-base.

TODO

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions