Theme Documentation
Tours is fully re-themeable. The visual system is built on Tailwind CSS whose color utilities are driven by CSS variables, declared in src/app/globals.css and wired into Tailwind in tailwind.config.ts. The default brand identity is blue, 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.cssdeclares the design tokens as CSS variables under:root(each color is a space-separated RGB triplet, e.g.59 130 246).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 still honor 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: { 500: "rgb(var(--brand-500) / <alpha-value>)", /* 50…950 */ },
secondary: { 500: "rgb(var(--secondary-500) / <alpha-value>)", /* 50…950 */ },
surface: "rgb(var(--surface) / <alpha-value>)",
"surface-2": "rgb(var(--surface-2) / <alpha-value>)",
heading: "rgb(var(--heading) / <alpha-value>)",
body: "rgb(var(--body) / <alpha-value>)",
line: "rgb(var(--line) / <alpha-value>)",
// `accent` and `ink` are STATIC hex scales (below) — not variable-driven.
}
Token groups
| Group | Tokens | Role |
|---|---|---|
| Brand | --brand-50 … --brand-950 |
Primary palette (blue). Buttons, links, active states, focus rings |
| Secondary | --secondary-50 … --secondary-950 |
Secondary palette (orange). Highlights, accents, gradient stops |
| Ink | ink-50 … ink-950 (static slate) |
Neutral scale for text, borders and surfaces |
| Accent | accent-50 … accent-900 (static orange) |
Fixed accent scale defined directly in the config |
| Surfaces | --surface, --surface-2 |
Page / panel backgrounds |
| Text | --heading, --body, --txt-muted |
Headings, body copy, secondary/muted text |
| Lines | --line |
Borders & dividers |
brandandsecondary(the re-themeable palettes) plus the semanticsurface / surface-2 / heading / body / linetokens are variable-driven.accentandinkare static scales defined directly intailwind.config.ts.
Brand scale — the real :root values (blue)
These are the exact default triplets from src/app/globals.css. The storefront overrides them within .site-theme when an admin picks a brand color.
:root {
/* Brand palette (blue default). Storefront overrides these within .site-theme. */
--brand-50: 239 246 255;
--brand-100: 219 234 254;
--brand-200: 191 219 254;
--brand-300: 147 197 253;
--brand-400: 96 165 250;
--brand-500: 59 130 246;
--brand-600: 37 99 235;
--brand-700: 29 78 216;
--brand-800: 30 64 175;
--brand-900: 30 58 138;
--brand-950: 23 37 84;
}
Secondary scale (orange) & semantic tokens
:root {
/* Secondary palette (orange default). Overridable from Theme Options → Secondary Color. */
--secondary-50: 255 247 237;
--secondary-100: 255 237 213;
--secondary-200: 254 215 170;
--secondary-300: 253 186 116;
--secondary-400: 251 146 60;
--secondary-500: 249 115 22;
--secondary-600: 234 88 12;
--secondary-700: 194 65 12;
--secondary-800: 154 52 18;
--secondary-900: 124 45 18;
--secondary-950: 67 20 7;
/* Semantic neutral tokens (light defaults). Dark mode + theme colors override these. */
--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;
}
Ink — the static neutral scale
ink-* is the neutral (slate) scale used for text, borders and surfaces throughout the app. It is fixed in tailwind.config.ts (not re-themeable), so neutrals stay consistent regardless of the chosen brand color.
// tailwind.config.ts (excerpt)
ink: {
50: "#f8fafc", 100: "#f1f5f9", 200: "#e2e8f0", 300: "#cbd5e1",
400: "#94a3b8", 500: "#64748b", 600: "#475569", 700: "#334155",
800: "#1e293b", 900: "#0f172a", 950: "#020617",
}
Use text-ink-* / border-ink-* / bg-ink-* for neutrals and bg-brand-* / text-brand-* / ring-brand-* for primary accents. Never hardcode a hex value in a component.
Light & dark mode
Dark mode is scoped to the storefront wrapper so the admin panel is unaffected: the dark overrides live under .site-theme.dark. Because every storefront surface is painted with the semantic utilities (bg-surface, text-heading, text-body, border-line, and the .site-theme remaps of bg-white / text-ink-* / border-ink-*), toggling the .dark class re-paints the whole storefront from these overrides — no per-component dark variants needed for neutrals.
/* 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;
}
The admin panel has its own cohesive dark palette (a slate scheme under html:has(.admin-shell.dark) that remaps the light Tailwind utilities), kept separate from the storefront theme.
Re-theming from the admin panel
Admins change the look under Admin → Theme Options → Appearance:
- Brand Color — overrides the
--brand-*scale (default blue). - Secondary Color — overrides the
--secondary-*scale (default orange). - Images — upload/format presets the
ImageUploadserver pipeline reads.
The chosen colors are injected as CSS-variable overrides on the .site-theme scope at runtime, so the catalog, tour pages, checkout and customer 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 {
/* The shipped default is blue (Tailwind blue-500 / 600 / 700). */
--brand-500: 59 130 246;
--brand-600: 37 99 235;
--brand-700: 29 78 216;
}
After editing, 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)) and the brand-gradient background image.
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:
h1, h2, h3, h4, h5, h6 {
@apply font-display tracking-tight;
}
Helper classes & tokens
globals.css also ships reusable component/utility classes that lean on the brand tokens:
| Class | Purpose |
|---|---|
.section / .section-title / .section-subtitle |
Consistent storefront section spacing & headings |
.badge / .badge-vibrant |
Brand-tinted pills (bg-brand-50 text-brand-700) |
.btn-vibrant |
Gradient-glow primary button (bg-brand-600 + brand ring) |
.glass / .glass-dark |
Frosted-glass surfaces |
.card-hover / .card-vibrant |
Lift-on-hover feature/pricing tiles |
.text-gradient |
Brand → secondary gradient headline text |
.scrollbar-thin / .thin-scroll |
Thin tinted scrollbars for panels & menus |
The .text-gradient and .brand-gradient background blend the brand and secondary tokens:
.text-gradient {
background-image: linear-gradient(120deg,
rgb(var(--brand-700)) 0%,
rgb(var(--brand-500)) 45%,
rgb(var(--secondary-500)) 100%);
}
Custom keyframes/animations (shimmer for skeletons, plus fade/slide helpers) round out the system.
© CreativeCape Solutions · creative-cape.com · support@creative-cape.com