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 configurationNote:
@quesby/coreis an npm package that is automatically installed when you runpnpm install. The SCSS files in@quesby/core/sass/are available because the package is listed as a dependency inpackage.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:
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:
@importis 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 modulesForward 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:
- Replace
@importwith@use - Create a
_forward.scssfile for shared variables and mixins - Use
@use "forward" as *;in files that need access to shared resources - Update variable references to use namespaced syntax when needed
3. Color System
Themes use SCSS maps to define colors for different visual themes:
$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, uselighten(),darken(), ormix()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:
: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:
# Development (with watch)npm run watch:css
# Production buildnpm run build:css
# Serve with CSS watchnpm run serveNote: For detailed development workflow, see the Development Guide.
2. Build Process
The build system:
- Compiles core SCSS from
src/sass/tosrc/assets/css/ - Compiles active theme SCSS from
src/themes/{theme}/tosrc/assets/css/ - Generates compressed CSS for production
- Watches for changes during development
3. File Output
Compiled CSS files:
src/assets/css/core.css- Core stylessrc/assets/css/skin.css- Theme stylessrc/assets/css/expressive-code.css- Code highlighting
Creating Custom Themes
1. Theme Structure
To create a new theme:
- Create a new directory in
src/themes/your-theme-name/ - Copy the structure from an existing theme
- Modify the SCSS files to match your design
- Update
site.jsonto 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.scssfile is essential for the modern@use/@forwardsystem 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.scssfile, which forwards the core mixins module.
Theme Development
1. Development Workflow
- Set your theme in
site.json - Run
npm run servefor development - Modify SCSS files in your theme directory
- 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.jsonmatches directory name - Ensure
skin.scssexists 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
@usestatements reference existing files - Ensure
_forward.scssfile exists and forwards required modules - Check for circular dependencies in
@usestatements - 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.scssis 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.scssfile 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
@usestatements that create circular references - Use
_forward.scssto 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.scssto 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
@useinstead of@importfor all new code - Create a
_forward.scssfile 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.scssfile 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.