Skip to main content
Squeditor allows you to manage multiple visual identities (branding, colors, typography) within a single codebase. This is achieved by mapping specific pages to discrete SCSS theme files and applying scoped CSS variables via a dedicated configuration.

1. The Configuration

Themes are defined in squeditor.config.js. Each theme entry controls how a specific set of pages is styled and packaged.
squeditor.config.js
module.exports = {
  themes: {
    'modern': {
      label: 'Modern Blue',
      bodyClass: 'theme-modern',           // The class added to <body>
      scss: 'src/assets/scss/themes/_modern.scss', // The entry point for this theme
      pages: ['index.php', 'about.php'],   // Pages that use this theme
      distSubfolder: '',                    // Subfolder in dist/ for these files
    },
    'saas': {
      label: 'Saas Tech',
      bodyClass: 'theme-saas',
      scss: 'src/assets/scss/themes/_saas.scss',
      pages: ['saas-landing.php'],
      distSubfolder: 'saas-demo',          // Packaged separately in dist/saas-demo
    }
  }
}

Property Reference

PropertyTypeDescription
Theme SlugstringThe unique ID (key) for the theme (e.g., 'saas'). Used in URL parameters and internal mapping.
labelstringThe human-readable name.
bodyClassstringThe CSS class applied to the <body> tag. All theme-specific SCSS variables are scoped to this class.
scssstringPath to the theme’s SCSS entry point.
pagesarrayList of .php files (relative to src/) that should default to this theme. Use '*' to match all.
distSubfolderstring(Optional) Subdirectory within dist/ where this theme’s static files will be saved during build, great for multi-purpose template.

2. The Theme SCSS File

Each theme SCSS file uses the sq-theme mixin. This mixin automatically generates scoped CSS variables (--sq-*) for both light and dark modes, applied to your theme’s bodyClass.
src/assets/scss/themes/_saas.scss
@include sq-theme(
    $selector: '.theme-saas',
    $colors: (
        'primary':      #271f20,
        'secondary':    #c3152f,
        'accent':       #fe7c72,
        'body-bg':      #ffffff,
        'body-text':    #1b1516,
    ),
    $dark-colors: (
        'primary':      #f8f5f0,
        'body-bg':      #1b1516,
        'body-text':    #f3f4f6,
    ),
    $overrides: (
        // Applied to BOTH Light and Dark unless specified otherwise
        'heading-font-weight':    600,
        'heading-line-height':    1.1,
        'heading-letter-spacing': -0.05em,
        'btn-radius':             0.75rem,
        // Optional Typography Presets
        'font-sans': "'Vidaloka', serif",
        'font-heading': "'Vidaloka', serif",
    ),
    $dark-overrides: (
        // Applied ONLY in Dark Mode
        // (Use this to tweak weights or spacing that looks different on dark backgrounds)
        'heading-font-weight':    400, 
    )
) {
    // Custom SCSS logic for this theme
    // Note: Use this only for complex niche-specific layout rules.
    // Logic-based token overrides should stay in the maps above.
}

Advanced Token Customization

Squeditor provides two maps for fine-grained token control:
  1. $overrides: Use this for tokens that should change globally for this theme (e.g., a “rounded” theme where everything has btn-radius: 50rem).
  2. $dark-overrides: Use this for tokens that specifically need adjustment in dark mode. For example, some fonts look thicker on dark backgrounds, so you might want to drop heading-font-weight from 600 (global) to 400 (dark only).

Why use Tokens vs. Manual CSS?

If you update @_base.scss (or the framework defaults) to use tokens:
/* _base.scss */
h1, h2, h3, h4, h5, h6 {
    font-weight: var(--sq-heading-font-weight, 700);
}
Then your theme files stay incredibly lean because you’re just changing the data (the variable value), and the framework handles the delivery (scoping it to the right body class and light/dark scheme).
Token SlugCSS PropertyCommon Values
heading-font-weightfont-weight300 (Light), 600 (Semi-Bold), 700 (Bold)
heading-line-heightline-height1, 1.1, 1.2
heading-letter-spacingletter-spacing-0.02em, -0.05em
btn-radiusborder-radius0rem (Sharp), 0.5rem (Soft), 99rem (Pill)
navbar-nav-gapgap1rem (Compact), 2.5rem (Spacious)

3. How It Works

** Token Override Mechanism ** Squeditor uses a “last-in-wins” approach. During the build process, the framework dynamically rewrites the last @import in your main.scss to target the active theme:
/* main.scss */
@import 'tokens';
@import 'base';
@import 'components';
@import 'utilities';

// REWRITTEN BY COMPILER
@import 'themes/saas'; 
Since the theme file imports last, its CSS variables override all global defaults seamlessly. ** Theme Detection ** The framework identifies the active theme in src/init.php based on:
  1. URL Query: ?theme=id (highest priority)
  2. Page Mapping: Matches the current PHP file against the pages array in your config.
  3. Default: Falls back to the first theme in your config if no match is found.

Demo Mode & Theme Switcher

If $site['demo_mode'] = true is set in your configuration, the Theme Switcher UI will appear. This allows users to manually cycle through your defined palettes and typography presets in the browser, overriding the default theme via query parameters and localStorage.

Playground: Common Scenarios

** Scenario A: Single Niche, Multiple Visual Styles ** Use this when building one template (e.g., a Portfolio) that you want to offer in multiple “flavors” (Clean, Bold, Pastel). All versions share the same pages.
themes: {
  'clean': {
    label: 'Clean Minimal',
    bodyClass: 'theme-clean',
    scss: 'src/assets/scss/themes/_clean.scss',
    pages: ['index.php', 'about.php', 'work.php'],
    distSubfolder: '', // Deployed to root
  },
  'bold': {
    label: 'High Contrast',
    bodyClass: 'theme-bold',
    scss: 'src/assets/scss/themes/_bold.scss',
    pages: ['index.php', 'about.php', 'work.php'],
    distSubfolder: 'demo-bold', // Accessible at /demo-bold/index.html
  }
}
** Scenario B: Multi-Niche with Subdirectories ** Use this when your project contains entirely different niches (e.g., Medical, SaaS, Creative) within a single showcase. Each niche has its own assets and separate distribution output.
themes: {
  'medical': {
    label: 'Medical Dental',
    bodyClass: 'theme-medical',
    scss: 'src/assets/scss/themes/_medical.scss',
    pages: ['medical/index.php', 'medical/services.php'],
    distSubfolder: 'medical-demo', 
  },
  'saas': {
    label: 'Professional Tech',
    bodyClass: 'theme-saas',
    scss: 'src/assets/scss/themes/_saas.scss',
    pages: ['saas/index.php', 'saas/features.php'],
    distSubfolder: 'saas-demo', 
  }
}
In this scenario, the build pipeline generates a clean dist/ structure:
  • dist/medical-demo/index.html (Styled with Medical theme)
  • dist/saas-demo/index.html (Styled with SaaS theme)