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
globals.cssdefines the design tokens as CSS variables under:root(as space-separated RGB triplets).tailwind.config.tsmaps each token to a Tailwind color usingrgb(var(--token) / <alpha-value>), so utilities likebg-brand-600,text-heading, andborder-lineresolve to those variables and respect opacity modifiers (bg-brand-600/30).- 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.
// 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:
brandandsecondary(the re-themeable palettes) plus the semanticsurface / heading / body / muted / linetokens are variable-driven.accentandinkare static scales defined directly intailwind.config.ts.
The default :root brand and semantic tokens:
: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.
/* 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
ImageUploadserver 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.
: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:
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 (
h1–h6) usefont-display(Raleway) via a base rule inglobals.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