Claude
Skills
Sign in
Back

multi-site-theming

Included with Lifetime
$97 forever

Use when implementing per-site themes, white-labeling, or brand override systems. Covers tenant-specific branding, theme inheritance, CSS variable hierarchies, and dynamic theme switching for multi-site CMS architectures.

Ads & Marketing

What this skill does


# Multi-Site Theming

Guidance for implementing per-site themes, white-labeling, and brand customization in multi-site CMS architectures.

## When to Use This Skill

- Implementing per-tenant or per-site branding
- Designing theme inheritance hierarchies
- Building white-label customization systems
- Configuring dynamic theme switching
- Managing brand overrides at runtime

## Theme Architecture

### Theme Hierarchy

```text
┌─────────────────────────────────────────────────────────────────┐
│                      THEME HIERARCHY                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │                    BASE THEME                            │   │
│   │  (Default colors, typography, spacing, components)       │   │
│   └─────────────────────────────────────────────────────────┘   │
│                              │                                   │
│                              ▼                                   │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │                   BRAND THEME                            │   │
│   │  (Corporate colors, fonts, logo, brand identity)         │   │
│   └─────────────────────────────────────────────────────────┘   │
│                              │                                   │
│                              ▼                                   │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │                   SITE THEME                             │   │
│   │  (Site-specific overrides, micro-branding)               │   │
│   └─────────────────────────────────────────────────────────┘   │
│                              │                                   │
│                              ▼                                   │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │                   USER PREFERENCES                       │   │
│   │  (Dark/light mode, accessibility, contrast)              │   │
│   └─────────────────────────────────────────────────────────┘   │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
```

## Theme Model

### Core Theme Entity

```csharp
public class Theme
{
    public Guid Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public string Slug { get; set; } = string.Empty;
    public ThemeType Type { get; set; }

    // Inheritance
    public Guid? ParentThemeId { get; set; }
    public Theme? ParentTheme { get; set; }

    // Scope
    public Guid? TenantId { get; set; }  // Null = global/base
    public Guid? SiteId { get; set; }    // Null = tenant-wide

    // Tokens
    public ThemeTokens Tokens { get; set; } = new();

    // Assets
    public ThemeAssets Assets { get; set; } = new();

    // Metadata
    public bool IsDefault { get; set; }
    public bool IsActive { get; set; }
    public DateTime CreatedUtc { get; set; }
    public DateTime? ModifiedUtc { get; set; }
}

public enum ThemeType
{
    Base,       // Foundation theme
    Brand,      // Tenant/brand level
    Site,       // Individual site
    Variant     // Light/dark variants
}

public class ThemeTokens
{
    // Colors
    public ColorTokens Colors { get; set; } = new();

    // Typography
    public TypographyTokens Typography { get; set; } = new();

    // Spacing
    public SpacingTokens Spacing { get; set; } = new();

    // Borders & Shadows
    public BorderTokens Borders { get; set; } = new();
    public ShadowTokens Shadows { get; set; } = new();

    // Component-specific overrides
    public Dictionary<string, Dictionary<string, string>> Components { get; set; } = new();
}

public class ColorTokens
{
    // Brand colors
    public string Primary { get; set; } = "#3B82F6";
    public string Secondary { get; set; } = "#6366F1";
    public string Accent { get; set; } = "#F59E0B";

    // Semantic colors
    public string Success { get; set; } = "#10B981";
    public string Warning { get; set; } = "#F59E0B";
    public string Error { get; set; } = "#EF4444";
    public string Info { get; set; } = "#3B82F6";

    // Surface colors
    public string Background { get; set; } = "#FFFFFF";
    public string Surface { get; set; } = "#F9FAFB";
    public string Border { get; set; } = "#E5E7EB";

    // Text colors
    public string TextPrimary { get; set; } = "#111827";
    public string TextSecondary { get; set; } = "#6B7280";
    public string TextMuted { get; set; } = "#9CA3AF";
}

public class ThemeAssets
{
    public string? LogoUrl { get; set; }
    public string? LogoDarkUrl { get; set; }
    public string? FaviconUrl { get; set; }
    public string? BackgroundImageUrl { get; set; }
    public List<string> FontUrls { get; set; } = new();
    public string? CustomCss { get; set; }
}
```

## Theme Resolution

### Cascading Theme Service

```csharp
public class ThemeResolver
{
    public async Task<ResolvedTheme> ResolveAsync(ThemeContext context)
    {
        var themes = new List<Theme>();

        // 1. Load base theme
        var baseTheme = await _repository.GetBaseThemeAsync();
        if (baseTheme != null) themes.Add(baseTheme);

        // 2. Load tenant/brand theme
        if (context.TenantId.HasValue)
        {
            var tenantTheme = await _repository.GetTenantThemeAsync(context.TenantId.Value);
            if (tenantTheme != null) themes.Add(tenantTheme);
        }

        // 3. Load site theme
        if (context.SiteId.HasValue)
        {
            var siteTheme = await _repository.GetSiteThemeAsync(context.SiteId.Value);
            if (siteTheme != null) themes.Add(siteTheme);
        }

        // 4. Apply user preferences (dark mode, contrast)
        if (context.UserPreferences != null)
        {
            var variantTheme = await ResolveVariantAsync(themes.Last(), context.UserPreferences);
            if (variantTheme != null) themes.Add(variantTheme);
        }

        // Merge themes in order
        return MergeThemes(themes);
    }

    private ResolvedTheme MergeThemes(IEnumerable<Theme> themes)
    {
        var resolved = new ResolvedTheme();

        foreach (var theme in themes)
        {
            // Later themes override earlier ones
            MergeTokens(resolved.Tokens, theme.Tokens);
            MergeAssets(resolved.Assets, theme.Assets);
        }

        return resolved;
    }
}

public class ThemeContext
{
    public Guid? TenantId { get; set; }
    public Guid? SiteId { get; set; }
    public UserPreferences? UserPreferences { get; set; }
}

public class UserPreferences
{
    public ColorScheme ColorScheme { get; set; } = ColorScheme.System;
    public bool HighContrast { get; set; }
    public bool ReducedMotion { get; set; }
}

public enum ColorScheme
{
    Light,
    Dark,
    System
}
```

## CSS Variable Generation

### Variable Generator

```csharp
public class CssVariableGenerator
{
    public string GenerateCssVariables(ResolvedTheme theme)
    {
        var sb = new StringBuilder();

        sb.AppendLine(":root {");

        // Colors
        GenerateColorVariables(sb, theme.Tokens.Colors);

        // Typography
        GenerateTypographyVariables(sb, theme.Tokens.Typography);

        // Spacing
        GenerateSpacingVariables(sb, theme.Tokens.Spacing);

        // Borders & Shadows
        GenerateBorderVariables(sb, theme.Tokens.Borders);
        GenerateShadowVariables(sb, theme.Tokens.Shadows);

        sb.AppendLine("}");

        // Dark mode variant
        if (theme.DarkVariant != null)
        {
            sb.AppendLine();
            sb.AppendLine("@media (prefers-color-scheme: dark) {");
            sb.AppendLine("  :root {");
            GenerateColorVariables(sb, theme.DarkVariant.Colors, "    ");
            sb.AppendLine("  }");
            sb.

Related in Ads & Marketing