Search...
Last updated: 18 November 2025

Quesby Theme System

Overview

The Quesby theme system is a SCSS-based styling architecture that allows you to customize the visual appearance of your website. The system uses modular SCSS files and CSS custom properties to provide flexible theming with support for multiple visual themes (light, dark).

System Structure

src/
└── themes/ # Theme directory
├── quesby-core/ # Default theme
│ ├── _base.scss # Base styles and CSS variables
│ ├── _blog.scss # Blog-specific styles
│ ├── _components.scss # Reusable components
│ ├── _documentation.scss # Documentation styles
│ ├── _forms.scss # Form elements
│ ├── _home.scss # Homepage styles
│ ├── _page.scss # General page styles
│ ├── _responsive.scss # Responsive breakpoints
│ ├── _theme-header.scss # Header component
│ ├── _theme-typography.scss # Typography system
│ ├── _theme-variables.scss # Theme color variables
│ └── skin.scss # Main theme file
└── quesby-brand-website/ # Alternative theme
└── [same structure]
@quesby/core (npm package)
├── sass/ # Core SCSS files
│ ├── _mixins.scss # SCSS mixins
│ ├── _reset.scss # CSS reset
│ ├── _typography.scss # Base typography
│ ├── _variables.scss # Core variables
│ └── core.scss # Main core file
└── _data/
└── site.json # Site configuration

Note: @quesby/core is an npm package that is automatically installed when you run pnpm install. The SCSS files in @quesby/core/sass/ are available because the package is listed as a dependency in package.json. This allows themes to import core styles using @use "@quesby/core/sass/_reset" and similar imports.

Theme Configuration

1. Theme Selection

Configure your active theme in src/_data/site.json:

{
"theme": "quesby-core",
"defaultVisualTheme": "dark"
}

Available Themes:

  • quesby-core (default)
  • quesby-brand-website

Note: For detailed configuration options, see the Configuration Guide.

2. Visual Theme Toggle

The system supports two visual themes that users can toggle:

  • Light Theme: Default light appearance
  • Dark Theme: Dark mode with inverted colors

The theme toggle is handled by JavaScript in src/assets/js/togglemode.js and persists user preference in localStorage.

JavaScript Implementation:

assets/js/togglemode.js
document.addEventListener('DOMContentLoaded', function() {
const themeToggle = document.getElementById('theme-toggle');
const currentTheme = localStorage.getItem('theme') || 'dark';
// Apply saved theme
document.documentElement.setAttribute('data-theme', currentTheme);
themeToggle?.addEventListener('click', function() {
const themes = ['light', 'dark'];
const currentIndex = themes.indexOf(currentTheme);
const nextTheme = themes[(currentIndex + 1) % themes.length];
document.documentElement.setAttribute('data-theme', nextTheme);
localStorage.setItem('theme', nextTheme);
});
});

CSS Fallback: Users without JavaScript will see the defaultVisualTheme from site.json.

Theme Architecture

1. Core SCSS Structure

Each theme follows this modular structure:

// skin.scss - Main theme file
@use "variables";
@use "@quesby/core/sass/_reset";
@use "@quesby/core/sass/_mixins";
@use "typography";
@use "base";
@use "forms";
@use "tables";
@use "components";
@use "header";
@use "footer";
@use "page";
@use "home";
@use "blog";
@use "search";
@use "documentation";
@use "responsive";

2. Modern Sass Module System

The theme system uses the modern @use and @forward rules instead of the legacy @import system. This provides better performance, explicit dependencies, and namespace control.

Key Benefits

  • Explicit Dependencies: Each file clearly declares what it needs
  • Namespace Control: Variables and mixins can be namespaced to avoid conflicts
  • Better Performance: Sass only compiles what's actually used
  • Future-Proof: @import is deprecated and will be removed in future Sass versions

Module Structure

Main Entry Point (skin.scss):

// Import core modules
@use "variables";
@use "@quesby/core/sass/_reset";
@use "@quesby/core/sass/_mixins";
// Import theme modules
@use "typography";
@use "base";
@use "forms";
// ... other modules

Forward Declarations (_forward.scss):

// Forward declarations for local theme modules
// This file allows other modules to access theme variables and mixins
@forward "variables";
@forward "@quesby/core/sass/_mixins";

Module Files (e.g., _components.scss):

@use "sass:map";
@use "forward" as *;
// Now you can use variables and mixins from the forwarded modules
.component {
margin-top: $margin * 3;
@include respond-to(tablet) {
// responsive styles
}
}

Namespace Usage

When you need to access specific modules without importing everything:

@use "variables" as vars;
@use "sass:map";
.theme-specific {
color: map.get(vars.$theme-light, text-fg);
}

Migration from @import

If migrating from the old @import system:

  1. Replace @import with @use
  2. Create a _forward.scss file for shared variables and mixins
  3. Use @use "forward" as *; in files that need access to shared resources
  4. Update variable references to use namespaced syntax when needed

3. Color System

Themes use SCSS maps to define colors for different visual themes:

_theme-variables.scss
$theme-light: (
text-fg: oklch(31.85% 0.018 18.1),
link-fg: color.adjust(white, $lightness: -10%),
bg: oklch(100% 0 0),
// ... more colors
);

SCSS Compatibility Note: color.adjust() requires Dart Sass 1.27.0+. For older versions, use lighten(), darken(), or mix() functions instead.

$theme-dark: (
text-fg: oklch(93% 0 0),
link-fg: oklch(84% 27% 45),
bg: oklch(15% 0 0),
// ... more colors
);

3. CSS Custom Properties

Colors are converted to CSS custom properties for runtime theme switching:

_base.scss
:root {
@each $name, $value in $theme-light {
--#{$name}: #{$value};
}
}
.dark {
@each $name, $value in $theme-dark {
--#{$name}: #{$value};
}
}

Build System

1. Sass Compilation

The build system compiles SCSS files using the following commands:

Terminal window
# Development (with watch)
npm run watch:css
# Production build
npm run build:css
# Serve with CSS watch
npm run serve

Note: For detailed development workflow, see the Development Guide.

2. Build Process

The build system:

  1. Compiles core SCSS from src/sass/ to src/assets/css/
  2. Compiles active theme SCSS from src/themes/{theme}/ to src/assets/css/
  3. Generates compressed CSS for production
  4. Watches for changes during development

3. File Output

Compiled CSS files:

  • src/assets/css/core.css - Core styles
  • src/assets/css/skin.css - Theme styles
  • src/assets/css/expressive-code.css - Code highlighting

Creating Custom Themes

1. Theme Structure

To create a new theme:

  1. Create a new directory in src/themes/your-theme-name/
  2. Copy the structure from an existing theme
  3. Modify the SCSS files to match your design
  4. Update site.json to use your theme

2. Essential Files

Required Files (Hard Requirements):

  • skin.scss - Main entry point (uses all other files)
  • _variables.scss - Color definitions for all visual themes
  • _typography.scss - Typography system
  • _base.scss - Base styles and CSS variables
  • _forward.scss - Forward declarations for shared resources

Optional Files (Theme-specific):

  • _blog.scss - Blog-specific styles (only if theme includes blog)
  • _documentation.scss - Documentation styles (only if theme includes docs)
  • _home.scss - Homepage styles (only if theme has custom homepage)
  • _components.scss - Reusable components
  • _forms.scss - Form elements
  • _page.scss - General page styles
  • _responsive.scss - Responsive breakpoints
  • _header.scss - Header component

Note: A minimal theme needs the 5 required files. The _forward.scss file is essential for the modern @use/@forward system to work properly.

3. Color Customization

Modify _variables.scss to change colors:

$theme-light: (
text-fg: #your-color,
link-fg: #your-link-color,
bg: #your-background,
// ... define all required colors
);

4. Typography Customization

Update _typography.scss for custom fonts:

:root {
--font-family-heading: 'Your Font', sans-serif;
--font-family-body: 'Your Body Font', sans-serif;
--font-size-base: 16px;
--line-height-base: 1.6;
}

Advanced Customization

1. CSS Custom Properties

Override theme variables using CSS custom properties:

:root {
--text-fg: #custom-color;
--bg: #custom-background;
--font-family-heading: 'Custom Font';
}

2. Component Styling

Create custom component styles:

.custom-button {
background: var(--link-fg);
color: var(--bg);
padding: 0.5rem 1rem;
border-radius: 4px;
border: none;
cursor: pointer;
&:hover {
opacity: 0.8;
}
}

3. Responsive Design

Use the responsive mixins and breakpoints with the modern module system:

@use "forward" as *;
.custom-layout {
display: flex;
@include respond-to(smartphone) {
flex-direction: column;
}
@include respond-to(tablet) {
flex-wrap: wrap;
}
}

Note: The responsive mixins are now available through the _forward.scss file, which forwards the core mixins module.

Theme Development

1. Development Workflow

  1. Set your theme in site.json
  2. Run npm run serve for development
  3. Modify SCSS files in your theme directory
  4. Changes are automatically compiled and reloaded

Note: For detailed development workflow, see the Development Guide.

2. Testing Themes

Test your theme across:

  • Different visual themes (light/dark)
  • Various screen sizes
  • Different browsers
  • Content types (blog, pages, documentation)

3. Performance Considerations

  • Use CSS custom properties for runtime theme switching
  • Minimize the number of color variations
  • Optimize SCSS compilation with proper imports
  • Test build times with large themes

Troubleshooting

Theme Not Loading

Problem: Theme styles not appearing Solutions:

  • Check theme name in site.json matches directory name
  • Ensure skin.scss exists in theme directory
  • Verify SCSS compilation is working (npm run build:css)
  • Check browser console for CSS errors

Colors Not Changing

Problem: Visual theme toggle not working Solutions:

  • Verify CSS custom properties are defined in _base.scss
  • Check JavaScript toggle functionality
  • Ensure theme classes (.dark) are applied
  • Test localStorage theme persistence

Build Errors

Problem: SCSS compilation fails Solutions:

  • Check SCSS syntax in theme files
  • Verify all @use statements reference existing files
  • Ensure _forward.scss file exists and forwards required modules
  • Check for circular dependencies in @use statements
  • Verify proper namespace usage when accessing variables/mixins
  • Ensure all required modules are properly forwarded in _forward.scss

Responsive Issues

Problem: Styles not responsive Solutions:

  • Verify _responsive.scss is imported
  • Check breakpoint definitions
  • Test media queries in browser dev tools
  • Ensure proper viewport meta tag

Module System Issues

Problem: Variables or mixins not found Solutions:

  • Ensure _forward.scss file exists and forwards the required modules
  • Check that files using variables/mixins have @use "forward" as *;
  • Verify the module being forwarded actually exports the required variables/mixins
  • Use namespaced imports (@use "module" as name;) for specific modules

Problem: Circular dependency errors Solutions:

  • Avoid @use statements that create circular references
  • Use _forward.scss to break circular dependencies
  • Restructure modules to have clear dependency hierarchy

Best Practices

1. Theme Organization

  • Keep related styles in appropriate files
  • Use descriptive variable names
  • Comment complex SCSS logic
  • Maintain consistent naming conventions
  • Use _forward.scss to centralize shared resources
  • Keep module dependencies clear and minimal

2. Color Management

  • Define all colors in _variables.scss
  • Use semantic color names (text-fg, bg, link-fg)
  • Test colors in all visual themes
  • Ensure sufficient contrast ratios

3. Performance

  • Minimize CSS output size
  • Use efficient selectors
  • Avoid deep nesting in SCSS
  • Optimize for critical rendering path

4. Module System

  • Use @use instead of @import for all new code
  • Create a _forward.scss file to share variables and mixins
  • Use @use "forward" as *; for files that need access to shared resources
  • Use namespaced imports (@use "module" as name;) when you need specific modules
  • Avoid circular dependencies between modules
  • Keep the _forward.scss file minimal and focused

5. Maintainability

  • Document custom variables and mixins
  • Keep themes modular and focused
  • Test changes across all content types
  • Version control theme changes

Integration with Eleventy

The theme system integrates with Eleventy through:

  • Global Data: Theme name available as {{ theme }} in templates
  • Watch Targets: Eleventy watches theme files for changes
  • Asset Pipeline: Compiled CSS is served as static assets
  • Template Variables: Theme information accessible in Nunjucks templates

Planned Ideas

These are potential future improvements to the theme system (not commitments):

  • Theme Marketplace: Community-driven theme repository
  • Visual Theme Builder: Web-based theme creation tool
  • Advanced Color Tools: Color palette generators and contrast checkers
  • Theme Validation: Automated testing for theme compatibility
  • Performance Monitoring: Built-in CSS performance metrics

Note: These are ideas for future development. Implementation depends on community interest and project priorities.