Theme Documentation

EduNest LMS is fully re-themeable. The visual system is built on Tailwind CSS 3 whose color tokens are driven by CSS variables, declared in src/app/globals.css and wired into utilities in tailwind.config.ts. The default brand identity is teal, with an orange secondary. Because the palettes are variables, an admin can re-skin the storefront from Theme Options → Appearance without touching code or rebuilding.


How theming works

  1. globals.css defines the design tokens as CSS variables under :root (as space-separated RGB triplets).
  2. tailwind.config.ts maps each token to a Tailwind color using rgb(var(--token) / <alpha-value>), so utilities like bg-brand-600, text-heading, and border-line resolve to those variables and respect opacity modifiers (bg-brand-600/30).
  3. The admin Theme Options → Appearance screen writes overrides scoped to the storefront wrapper class .site-theme, so the admin panel's own chrome is never affected by a customer's brand color.
TS
// tailwind.config.ts (excerpt)
colors: {
  brand:     { 600: "rgb(var(--brand-600) / <alpha-value>)", /* 50…950 */ },
  secondary: { 600: "rgb(var(--secondary-600) / <alpha-value>)", /* 50…950 */ },
  surface:   "rgb(var(--surface) / <alpha-value>)",
  heading:   "rgb(var(--heading) / <alpha-value>)",
  body:      "rgb(var(--body) / <alpha-value>)",
  muted:     "rgb(var(--muted) / <alpha-value>)",
  line:      "rgb(var(--line) / <alpha-value>)",
}

Token groups

Group Tokens Role
Brand --brand-50--brand-950 Primary palette (teal). Buttons, links, active states, focus rings
Secondary --secondary-50--secondary-950 Secondary palette (orange). Highlights, accents
Accent accent-50…900 (static, orange) Fixed accent scale in the config
Ink ink-50…900 (static, slate) Neutral slate scale for borders/text
Surfaces --surface, --surface-2 Page / panel backgrounds
Text --heading, --body, --txt-muted (muted) Headings, body copy, secondary text
Lines --line Borders & dividers

Note: brand and secondary (the re-themeable palettes) plus the semantic surface / heading / body / muted / line tokens are variable-driven. accent and ink are static scales defined directly in tailwind.config.ts.

The default :root brand and semantic tokens:

CSS
:root {
  /* Brand palette (teal default). Storefront overrides these within .site-theme. */
  --brand-500: 20 184 166;
  --brand-600: 13 148 136;
  --brand-700: 15 118 110;

  /* Secondary palette (orange default). */
  --secondary-500: 249 115 22;
  --secondary-600: 234 88 12;

  /* Semantic neutral tokens (light defaults). */
  --surface:   255 255 255;
  --surface-2: 248 250 252;
  --heading:   15 23 42;
  --body:      30 41 59;
  --txt-muted: 100 116 139;
  --line:      226 232 240;
}

Light & dark mode

Dark mode uses Tailwind's class strategy — darkMode: "class" in tailwind.config.ts. Dark mode is scoped to the storefront wrapper so the admin panel is unaffected: the dark token overrides live under .site-theme.dark.

CSS
/* Dark mode is scoped to the storefront wrapper (.site-theme.dark). */
.site-theme.dark {
  --surface:   17 24 39;
  --surface-2: 30 41 59;
  --heading:   248 250 252;
  --body:      203 213 225;
  --txt-muted: 148 163 184;
  --line:      51 65 85;
}

Because every storefront surface is painted with bg-surface, text-heading, text-body, border-line, etc., flipping the .dark class on the .site-theme wrapper re-paints the whole storefront from these overrides — no per-component dark variants required for the neutral palette.


Re-theming from the admin panel

Admins change the look under Admin → Theme Options → Appearance:

  • Brand Color — overrides the --brand-* scale (default teal).
  • Secondary Color — overrides the --secondary-* scale (default orange).
  • Images — upload/format presets that the ImageUpload server pipeline reads.

The chosen colors are injected as CSS-variable overrides on the .site-theme scope at runtime, so the catalog, course pages, checkout, and learner area all re-skin instantly. The admin UI keeps its own fixed brand-tinted chrome.

Changing the brand color in code

To change the default permanently, edit the --brand-* triplets in src/app/globals.css. Values are space-separated RGB channels (not hex), so Tailwind's <alpha-value> opacity modifiers keep working.

CSS
:root {
  /* Example: switch the default brand from teal to indigo */
  --brand-500: 99 102 241;   /* indigo-500 */
  --brand-600: 79 70 229;    /* indigo-600 */
  --brand-700: 67 56 202;    /* indigo-700 */
}

After this, every bg-brand-600, text-brand-700, ring-brand-500, etc. across the app reflects the new color — including derived tokens such as the glow shadow (0 10px 40px rgb(var(--brand-500) / 0.30)).


Typography

Fonts are bound to CSS variables provided by next/font and mapped in tailwind.config.ts:

TS
fontFamily: {
  sans:    ["var(--font-inter)",   "system-ui", "sans-serif"], // body
  display: ["var(--font-raleway)", "system-ui", "sans-serif"], // headings
}
  • Body copy uses font-sans (Inter).
  • Headings (h1h6) use font-display (Raleway) via a base rule in globals.css.

Helper classes & tokens

globals.css also ships a handful of reusable component/utility classes that lean on the brand tokens:

Class Purpose
.section / .section-title / .section-subtitle Consistent storefront section spacing & headings
.badge Brand-tinted pill (bg-brand-50 text-brand-700)
.glass / .glass-dark Frosted-glass surfaces
.card-hover Lift-on-hover transition
.scrollbar-thin Thin teal-tinted scrollbar (storefront)
.scrollbar-thin-dark Thin slate scrollbar (admin sidebar)

Custom keyframes/animations are also defined: fade-up, fade-in, and shimmer.


© CreativeCape Solutions · creative-cape.com · support@creative-cape.com

Theme Documentation — EduNest Docs | EduNest