WebSpark.Bootswatch 1.34.0

dotnet add package WebSpark.Bootswatch --version 1.34.0
                    
NuGet\Install-Package WebSpark.Bootswatch -Version 1.34.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="WebSpark.Bootswatch" Version="1.34.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="WebSpark.Bootswatch" Version="1.34.0" />
                    
Directory.Packages.props
<PackageReference Include="WebSpark.Bootswatch" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add WebSpark.Bootswatch --version 1.34.0
                    
#r "nuget: WebSpark.Bootswatch, 1.34.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package WebSpark.Bootswatch@1.34.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=WebSpark.Bootswatch&version=1.34.0
                    
Install as a Cake Addin
#tool nuget:?package=WebSpark.Bootswatch&version=1.34.0
                    
Install as a Cake Tool

WebSpark.Bootswatch

A .NET Razor Class Library that provides seamless integration of Bootswatch themes into ASP.NET Core applications. Built on Bootstrap 5, this library offers modern, responsive theming with dynamic theme switching, light/dark mode support, and comprehensive caching mechanisms.

Multi-Framework Support: Targets .NET 8.0 (LTS), .NET 9.0 (STS), and .NET 10.0 for maximum compatibility.

NuGet Version NuGet Downloads GitHub License .NET Multi-Framework Tests GitHub Stars

Latest Release: v1.34.0 - Demo site UI improvements for better theme visibility

โœจ Features

  • ๐ŸŽจ Complete Bootswatch Integration: All official Bootswatch themes plus custom themes
  • ๐ŸŒ“ Light/Dark Mode Support: Automatic theme detection and switching
  • โšก High Performance: Built-in caching with StyleCache service
  • ๐Ÿ”ง Easy Integration: Single-line setup with extension methods
  • ๐Ÿ“ฑ Responsive Design: Mobile-first Bootstrap 5 foundation
  • ๐ŸŽฏ Tag Helper Support: <bootswatch-theme-switcher /> for easy UI integration
  • ๐Ÿ”’ Production Ready: Comprehensive error handling and fallback mechanisms
  • ๐Ÿ“– Full Documentation: IntelliSense support and XML documentation
  • ๐ŸŽ Multi-Framework: Supports .NET 8.0 (LTS), 9.0 (STS), and 10.0

โš ๏ธ IMPORTANT: Required Dependencies

WebSpark.Bootswatch requires WebSpark.HttpClientUtility to be installed AND registered separately.

โœ… Quick Setup Checklist

Before starting, ensure you complete ALL of these steps:

  • Install both packages: WebSpark.Bootswatch AND WebSpark.HttpClientUtility
  • Add both using statements to Program.cs
  • Register AddHttpClientUtility() BEFORE AddBootswatchThemeSwitcher()
  • Add required configuration to appsettings.json
  • Use UseBootswatchAll() BEFORE UseStaticFiles() in middleware pipeline

Missing any of these steps will cause runtime errors!

Common Setup Mistake

// โŒ WRONG - Missing HttpClientUtility registration
builder.Services.AddBootswatchThemeSwitcher();

// โœ… CORRECT - HttpClientUtility registered first
using WebSpark.Bootswatch;
using WebSpark.HttpClientUtility;

builder.Services.AddHttpClientUtility();      // Must be FIRST
builder.Services.AddBootswatchThemeSwitcher(); // Then this

๐Ÿ“‹ Prerequisites

Framework Support

The library supports multiple .NET versions:

Framework Status Support Level
.NET 8.0 โœ… Supported LTS (Long Term Support)
.NET 9.0 โœ… Supported STS (Standard Term Support)
.NET 10.0 โœ… Supported Current Release

Your project can target any of these frameworks and will receive the appropriate version of the library.

Required Dependencies

<PackageReference Include="WebSpark.Bootswatch" Version="1.34.0" />
<PackageReference Include="WebSpark.HttpClientUtility" Version="2.1.1" />

Configuration Requirements

Add to your appsettings.json for dynamic theme fetching:

{
  "CsvOutputFolder": "c:\\temp\\WebSpark\\CsvOutput",
  "HttpRequestResultPollyOptions": {
    "MaxRetryAttempts": 3,
    "RetryDelaySeconds": 1,
    "CircuitBreakerThreshold": 3,
    "CircuitBreakerDurationSeconds": 10
  }
}

๐Ÿ› ๏ธ Installation

Package Manager Console

Install-Package WebSpark.Bootswatch
Install-Package WebSpark.HttpClientUtility

.NET CLI

dotnet add package WebSpark.Bootswatch
dotnet add package WebSpark.HttpClientUtility

PackageReference

<PackageReference Include="WebSpark.Bootswatch" Version="1.34.0" />
<PackageReference Include="WebSpark.HttpClientUtility" Version="2.1.1" />

The NuGet package automatically selects the correct assembly based on your project's target framework.

โšก Quick Start

Step 1: Install BOTH Required Packages

# Install WebSpark.Bootswatch
dotnet add package WebSpark.Bootswatch

# Install REQUIRED dependency (NOT automatically installed)
dotnet add package WebSpark.HttpClientUtility

Verify Installation: Your .csproj should now include BOTH packages:

<PackageReference Include="WebSpark.Bootswatch" Version="1.34.0" />
<PackageReference Include="WebSpark.HttpClientUtility" Version="2.1.1" />

Step 2: Add Required Configuration

Create or update appsettings.json:

{
  "CsvOutputFolder": "c:\\temp\\WebSpark\\CsvOutput",
  "HttpRequestResultPollyOptions": {
    "MaxRetryAttempts": 3,
    "RetryDelaySeconds": 1,
    "CircuitBreakerThreshold": 3,
    "CircuitBreakerDurationSeconds": 10
  },
  "BootswatchOptions": {
    "DefaultTheme": "yeti",
    "EnableCaching": true,
    "CacheDurationMinutes": 60
  }
}

Step 3: Configure Services in Program.cs

Add using statements at the top:

using WebSpark.Bootswatch;
using WebSpark.HttpClientUtility;

Register services in the correct order:

var builder = WebApplication.CreateBuilder(args);

// Add services
builder.Services.AddRazorPages();
builder.Services.AddHttpContextAccessor();

// โš ๏ธ CRITICAL: Register HttpClientUtility FIRST
builder.Services.AddHttpClientUtility();

// Then register Bootswatch theme switcher
builder.Services.AddBootswatchThemeSwitcher();

var app = builder.Build();

// Configure middleware pipeline
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

// โš ๏ธ CRITICAL: UseBootswatchAll() must come BEFORE UseStaticFiles()
app.UseBootswatchAll();
app.UseStaticFiles();

app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();

app.Run();

Step 4: Update _ViewImports.cshtml

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, WebSpark.Bootswatch

Step 5: Update _Layout.cshtml

Add required using statements and inject StyleCache:

@using WebSpark.Bootswatch.Services
@using WebSpark.Bootswatch.Helpers
@inject StyleCache StyleCache

Update the HTML structure:

<!DOCTYPE html>
<html lang="en" data-bs-theme="@(BootswatchThemeHelper.GetCurrentColorMode(Context))">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"]</title>
    @{
        var themeName = BootswatchThemeHelper.GetCurrentThemeName(Context);
        var themeUrl = BootswatchThemeHelper.GetThemeUrl(StyleCache, themeName);
    }
    <link id="bootswatch-theme-stylesheet" rel="stylesheet" href="@themeUrl" />
    <script src="/_content/WebSpark.Bootswatch/js/bootswatch-theme-switcher.js"></script>
    
    
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" />
</head>
<body>
    <nav class="navbar navbar-expand-lg">
        <div class="container">
            <a class="navbar-brand" href="/">My App</a>
            <ul class="navbar-nav ms-auto">
                
                
                
                <bootswatch-theme-switcher />
            </ul>
        </div>
    </nav>
    
    <main>
        @RenderBody()
    </main>
    
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

Step 6: Verify Setup

Build and run your application:

dotnet build
dotnet run

Expected Results:

  • โœ… Application starts without errors
  • โœ… Theme switcher appears in navigation
  • โœ… Default theme is applied
  • โœ… Theme switching works
  • โœ… Light/dark mode toggle functions

โš ๏ธ Common Errors & Solutions

Error: "Unable to resolve service for type 'IHttpRequestResultService'"

Full Error Message:

System.AggregateException: Some services are not able to be constructed 
(Error while validating the service descriptor 'ServiceType: WebSpark.Bootswatch.Model.IStyleProvider 
Lifetime: Scoped ImplementationType: WebSpark.Bootswatch.Provider.BootswatchStyleProvider': 
Unable to resolve service for type 'WebSpark.HttpClientUtility.RequestResult.IHttpRequestResultService'

Cause: WebSpark.HttpClientUtility services are not registered.

Solution:

  1. Verify package is installed: dotnet list package | findstr HttpClientUtility
  2. Add using statement: using WebSpark.HttpClientUtility;
  3. Register services BEFORE Bootswatch:
using WebSpark.Bootswatch;
using WebSpark.HttpClientUtility;

builder.Services.AddHttpClientUtility();      // โœ… Must be FIRST
builder.Services.AddBootswatchThemeSwitcher(); // โœ… Then this

Error: "Themes not loading" or "404 errors for theme files"

Cause: Middleware is in wrong order.

Solution: Ensure UseBootswatchAll() comes BEFORE UseStaticFiles():

// โœ… CORRECT ORDER
app.UseBootswatchAll();    // First
app.UseStaticFiles();      // Then this

// โŒ WRONG ORDER (will fail)
app.UseStaticFiles();
app.UseBootswatchAll();

Error: "Configuration section not found"

Cause: Missing or incorrect appsettings.json configuration.

Solution: Ensure ALL required sections are present in appsettings.json:

{
  "CsvOutputFolder": "c:\\temp\\WebSpark\\CsvOutput",
  "HttpRequestResultPollyOptions": {
    "MaxRetryAttempts": 3,
    "RetryDelaySeconds": 1,
    "CircuitBreakerThreshold": 3,
    "CircuitBreakerDurationSeconds": 10
  }
}

Error: Theme switcher not visible

Cause: Tag helper not registered in _ViewImports.cshtml.

Solution: Add to _ViewImports.cshtml:

@addTagHelper *, WebSpark.Bootswatch

๐ŸŽฏ Advanced Usage

StyleCache Service

public class HomeController : Controller
{
    private readonly StyleCache _styleCache;

    public HomeController(StyleCache styleCache)
    {
        _styleCache = styleCache;
    }

    public IActionResult Index()
    {
        // Get all available themes
        var allThemes = _styleCache.GetAllStyles();
        
        // Get specific theme
        var defaultTheme = _styleCache.GetStyle("default");
        
        return View(allThemes);
    }
}

Theme Helper Methods

// Get current theme information
var currentTheme = BootswatchThemeHelper.GetCurrentThemeName(Context);
var colorMode = BootswatchThemeHelper.GetCurrentColorMode(Context);
var themeUrl = BootswatchThemeHelper.GetThemeUrl(StyleCache, currentTheme);

// Generate theme switcher HTML
var switcherHtml = BootswatchThemeHelper.GetThemeSwitcherHtml(StyleCache, Context);

Custom Theme Integration

// Add custom themes to your StyleCache
public void ConfigureServices(IServiceCollection services)
{
    services.AddBootswatchThemeSwitcher();
    services.Configure<BootswatchOptions>(options =>
    {
        options.CustomThemes.Add(new StyleModel
        {
            Name = "custom-theme",
            Description = "My Custom Theme",
            CssPath = "/css/custom-theme.css"
        });
    });
}

๐Ÿงช Testing & Demo

Demo Project

Explore the complete implementation in our demo project:

git clone https://github.com/MarkHazleton/WebSpark.Bootswatch.git
cd WebSpark.Bootswatch
dotnet run --project WebSpark.Bootswatch.Demo

The demo showcases:

  • โœ… All Bootswatch themes
  • โœ… Light/dark mode switching
  • โœ… Responsive design patterns
  • โœ… Integration examples
  • โœ… Performance optimizations

Multi-Framework Testing

The library includes comprehensive tests that run on all supported frameworks:

# Test all frameworks
dotnet test

# Test specific framework
dotnet test --framework net8.0
dotnet test --framework net9.0
dotnet test --framework net10.0

# Use PowerShell script for detailed output
.\run-multi-framework-tests.ps1

Our CI/CD pipeline runs separate test jobs for each framework, ensuring compatibility across all supported .NET versions.

๐Ÿ—๏ธ Architecture

Core Components

Component Purpose Lifecycle
StyleCache Theme data caching Singleton
BootswatchStyleProvider Theme management Scoped
BootswatchThemeHelper Static utilities Static
BootswatchThemeSwitcherTagHelper UI component Transient

Middleware Pipeline

The correct middleware order is crucial:

app.UseBootswatchStaticFiles(); // 1. Bootswatch static files
app.UseStaticFiles();           // 2. Application static files  
app.UseRouting();               // 3. Routing

Multi-Framework Package Structure

The NuGet package contains separate assemblies for each target framework:

WebSpark.Bootswatch.1.31.0.nupkg
โ”œโ”€โ”€ lib/
โ”‚   โ”œโ”€โ”€ net8.0/
โ”‚   โ”‚   โ””โ”€โ”€ WebSpark.Bootswatch.dll
โ”‚   โ”œโ”€โ”€ net9.0/
โ”‚   โ”‚   โ””โ”€โ”€ WebSpark.Bootswatch.dll
โ”‚   โ””โ”€โ”€ net10.0/
โ”‚       โ””โ”€โ”€ WebSpark.Bootswatch.dll

Each assembly is compiled with framework-specific optimizations and references the appropriate version of dependencies.

๐Ÿ”ง Configuration Options

Middleware Configuration

// Full configuration
app.UseBootswatchAll();

// Or individual components
app.UseBootswatchStaticFiles();
app.UseBootswatchThemeRoutes();

Service Configuration

services.AddBootswatchThemeSwitcher(options =>
{
    options.DefaultTheme = "bootstrap";
    options.EnableCaching = true;
    options.CacheDurationMinutes = 60;
});

๐Ÿš€ Performance

Caching Strategy

  • Theme Data: Cached in StyleCache singleton
  • HTTP Requests: Resilient HTTP client with Polly
  • Static Files: Embedded resources with cache headers
  • Background Loading: Non-blocking theme initialization

Bundle Optimization

  • CSS: Minified Bootswatch themes
  • JavaScript: Lightweight theme switcher (~2KB)
  • Icons: Optimized SVG assets

Framework-Specific Optimizations

Each target framework receives optimized builds:

  • .NET 8.0: LTS-optimized with proven stability
  • .NET 9.0: Enhanced performance features
  • .NET 10.0: Latest runtime optimizations

๐Ÿ”’ Security

  • โœ… Input Validation: Theme names sanitized and validated
  • โœ… XSS Protection: HTML encoding in all outputs
  • โœ… HTTPS: Secure external resource loading
  • โœ… CSP Friendly: No inline scripts or styles
  • โœ… CORS Compliant: Proper resource sharing policies

๐Ÿ› ๏ธ Troubleshooting

For detailed troubleshooting, see the Common Errors & Solutions section above.

Quick Reference

Issue Solution
Service resolution error Register AddHttpClientUtility() before AddBootswatchThemeSwitcher()
Themes not loading Check middleware order: UseBootswatchAll() before UseStaticFiles()
Theme switcher not visible Ensure @addTagHelper *, WebSpark.Bootswatch in _ViewImports.cshtml
Missing dependencies Install WebSpark.HttpClientUtility package
Configuration errors Add required appsettings.json configuration
Wrong framework version NuGet automatically selects correct version based on your target framework

Debug Mode

Enable detailed logging:

builder.Services.AddLogging(config =>
{
    config.AddConsole();
    config.SetMinimumLevel(LogLevel.Debug);
});

๐Ÿ“Š Browser Support

Browser Version Status
Chrome 90+ โœ… Fully Supported
Firefox 88+ โœ… Fully Supported
Safari 14+ โœ… Fully Supported
Edge 90+ โœ… Fully Supported
IE 11 โŒ Not Supported

๐Ÿค Contributing

We welcome contributions! Please see CONTRIBUTING.md for guidelines.

Development Setup

# Clone repository
git clone https://github.com/MarkHazleton/WebSpark.Bootswatch.git
cd WebSpark.Bootswatch

# Restore dependencies
dotnet restore

# Build solution (builds for all target frameworks)
dotnet build

# Run tests (tests all frameworks)
dotnet test

# Run demo
dotnet run --project WebSpark.Bootswatch.Demo

Testing Contributions

When contributing, ensure your changes work across all target frameworks:

# Run comprehensive multi-framework tests
.\run-multi-framework-tests.ps1 -Configuration Release

Contribution Areas

  • ๐Ÿ› Bug fixes and improvements
  • ๐Ÿ“š Documentation enhancements
  • ๐ŸŽจ New theme contributions
  • ๐Ÿงช Test coverage expansion
  • ๐Ÿš€ Performance optimizations
  • ๐ŸŽฏ Framework-specific optimizations

๐Ÿ“ Changelog

[1.34.0] - 2025-12-03

  • ๐ŸŽจ Demo Site UI Improvements: Enhanced hero section visibility across all themes
  • ๐ŸŽจ Better Contrast: Added shadow effects and explicit color classes for readability
  • ๐ŸŽจ Typography Enhancements: Improved visual hierarchy with better weights
  • โœ… No Library Changes: Demo-only improvements, library remains unchanged
  • โœ… No Breaking Changes: Fully backward compatible

[1.33.0] - 2025-12-03

  • โœ… Dependency Validation: Automatic detection of missing required services
  • โœ… Configuration Validation: Startup validation service with helpful warnings
  • โœ… Enhanced XML Documentation: Comprehensive IntelliSense with code examples
  • โœ… Improved Error Messages: Clear, actionable error messages with solutions
  • ๐Ÿ“š README Rewrite: Complete step-by-step setup guide with troubleshooting
  • โœ… No Breaking Changes: Fully backward compatible

[1.31.0] - 2025-01-13

  • โœ… Multi-Framework Support: Added .NET 8.0, 9.0, and 10.0 targeting
  • โœ… Updated Dependencies: Framework-specific package versions
  • โœ… Comprehensive Testing: Multi-framework test suite with CI/CD
  • โœ… Removed Legacy Code: Eliminated System.Text.RegularExpressions (now in BCL)
  • โœ… No Breaking Changes: Fully backward compatible

[1.30.0] - 2025-01-07

  • โœ… Updated all NuGet dependencies to latest versions
  • โœ… Enhanced security with latest dependency versions
  • โœ… No breaking changes

[1.10.3] - 2025-05-20

  • โœ… Patch release with minor improvements
  • โœ… Enhanced logging and diagnostics

[1.10.0] - 2025-05-15

  • โœ… Added Bootswatch Theme Switcher Tag Helper
  • โœ… Included sample layout file in NuGet package
  • โœ… Improved documentation and integration guides

View Full Changelog

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

Third-Party Licenses

  • Bootstrap: MIT License
  • Bootswatch: MIT License
  • WebSpark.HttpClientUtility: MIT License

See NOTICE.txt for complete attribution.

๐Ÿ™ Acknowledgments

  • Bootstrap Team - For the amazing Bootstrap framework
  • Thomas Park - Creator of Bootswatch themes
  • .NET Team - For excellent multi-targeting support
  • Contributors - Everyone who has contributed to this project

๐Ÿ“ž Support


<div align="center"> <p>Made with โค๏ธ by <a href="https://github.com/MarkHazleton">Mark Hazleton</a></p> <p> <a href="https://github.com/MarkHazleton/WebSpark.Bootswatch">โญ Star this repo</a> โ€ข <a href="https://github.com/MarkHazleton/WebSpark.Bootswatch/fork">๐Ÿ”€ Fork</a> โ€ข <a href="https://github.com/MarkHazleton/WebSpark.Bootswatch/issues">๐Ÿ› Report Bug</a> โ€ข <a href="https://github.com/MarkHazleton/WebSpark.Bootswatch/discussions">๐Ÿ’ฌ Discuss</a> </p> </div>

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.34.0 196 12/4/2025
1.32.0 292 11/13/2025
1.30.0 129 9/27/2025
1.20.1 222 7/1/2025
1.10.3 216 5/21/2025
1.10.2 205 5/20/2025
1.10.1 218 5/18/2025
1.10.0 289 5/15/2025
1.0.7 292 5/15/2025
1.0.6 231 5/5/2025
1.0.5 216 5/5/2025
1.0.4 215 5/4/2025
1.0.3 203 5/4/2025
1.0.2 190 5/4/2025

Version 1.34.0: Demo site UI improvements

     DEMO SITE ENHANCEMENTS:
     - 🎨 Improved hero section visibility across all 28 themes
     - 🎨 Enhanced text contrast with shadow effects and explicit color classes
     - 🎨 Better visual hierarchy with improved typography weights
     - 🎨 Ensures readability in both light and dark mode themes

     LIBRARY CHANGES: None - This is a demo-only release
     BREAKING CHANGES: None - Fully backward compatible

     Previous version 1.33.0: Enhanced developer experience with dependency validation,
     configuration validation service, comprehensive XML documentation, and improved error
     messages.
     Complete README rewrite with step-by-step setup guide and troubleshooting section.

     SETUP REQUIREMENTS:
     1. Install: dotnet add package WebSpark.HttpClientUtility
     2. Register: builder.Services.AddHttpClientUtility(); (BEFORE AddBootswatchThemeSwitcher)
     3. Add HttpRequestResultPollyOptions to appsettings.json
     4. Use UseBootswatchAll() BEFORE UseStaticFiles()

     For complete setup guide, see:
     https://github.com/MarkHazleton/WebSpark.Bootswatch/wiki/Getting-Started