LMS course project theme¶
CMS authors configure a project theme per course (preset + colour/typography overrides). The LMS applies that theme on all course routes so the course sidebar, landing page, and entry content share the same branding.
Data flow¶
- CMS stores
projects.theme_settingsand resolves CSS viagenerateThemeCss(see CMS theme system inapps/cms/docs/reference/theme-system.md). - LMS calls
GET /projects/{id}/page-hierarchy?expand=projectThemeonce pergetCourseBySlug. - The API returns
projectThemeCsswith LMS-safe scoping: colours under:root:not(.dark) [data-course-project-theme], and typography/custom CSS on[data-course-project-theme](including mirrored--sidebar*tokens for the shadcn course sidebar). CourseProjectThemeinjects the style block and wraps course UI indata-course-project-theme.- Entry lesson/quiz/assignment bodies use
CmsAuthoredPagePreviewBodywithincludeProjectThemeStyle={false}so theme is not duplicated.
Routes¶
| Route | Wrapper |
|---|---|
/learn/course/\[slug\] (landing) |
CourseProjectTheme on the page |
/learn/course/\[slug\]/entry/* |
CourseProjectTheme in the entry layout (sidebar + main) |
Site chrome (header, footer, light/dark theme toggle, and font-size toggle) is outside the scoped wrapper and keeps tenant-level styling.
Site project theme¶
The LMS site project (CMS_PROJECT_UUID) also exposes projectThemeCss through GET /projects/{id}/pages/{pageId}?expand=projectTheme.
getSiteProjectThemeresolves the site hierarchy, pickshome(fallback first top-level page), and readsprojectThemeCss.SiteProjectThemeinjects that CSS once insrc/app/[locale]/layout.tsx, before site chrome.- Public and learner routes now share one app-wide site theme source (including
/learn), while course-specific branding remains isolated to[data-course-project-theme]. - LMS dark-mode compatibility is intentional: site colours are scoped to
:root:not(.dark), so dark mode falls back to shared design-token dark values while CMS typography and custom CSS still apply in both modes.
User font-size preference: learners adjust reading scale from the site header font-size menu. The LMS applies a multiplier at the <html> root on top of --font-size-base when the site theme defines one; Medium equals that CMS base (or the browser default). Course-scoped [data-course-project-theme] branding is unchanged — only the learner's reading scale changes. See Learner Experience — Site header preferences.
Related docs¶
- entry-pagination.md —
course-sidebartest IDs and shell layout - CMS theme system (
apps/cms/docs/reference/theme-system.md) — token mirroring and API expand