Heroicsoft.NetForge.Components 1.1.1

dotnet add package Heroicsoft.NetForge.Components --version 1.1.1
                    
NuGet\Install-Package Heroicsoft.NetForge.Components -Version 1.1.1
                    
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="Heroicsoft.NetForge.Components" Version="1.1.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Heroicsoft.NetForge.Components" Version="1.1.1" />
                    
Directory.Packages.props
<PackageReference Include="Heroicsoft.NetForge.Components" />
                    
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 Heroicsoft.NetForge.Components --version 1.1.1
                    
#r "nuget: Heroicsoft.NetForge.Components, 1.1.1"
                    
#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 Heroicsoft.NetForge.Components@1.1.1
                    
#: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=Heroicsoft.NetForge.Components&version=1.1.1
                    
Install as a Cake Addin
#tool nuget:?package=Heroicsoft.NetForge.Components&version=1.1.1
                    
Install as a Cake Tool

<img src="https://github.com/gordon-matt/Heroicsoft.NetForge/blob/master/_Misc/Logo-Wide.jpg" alt="Logo" width="100%" />

Shared building blocks for the self-hosted MVC and Blazor apps. Authentication, result helpers, and the Hangfire dashboard filter are used by both. The two Blazor component packages share the same component names and services: use Heroicsoft.NetForge.Components.Bootstrap for apps built on Bootstrap and Bootswatch, and Heroicsoft.NetForge.Components for apps that use the NetForge nf- style (light and dark, no Bootstrap).

Packages

Package What it replaces
Heroicsoft.NetForge.Abstractions AuthProvider, IUserContextService, BootswatchThemes, AppVersion, DatabaseProviders, setup status, nav models
Heroicsoft.NetForge.Results ResultExtensions (To<T>, GetDisplayMessage)
Heroicsoft.NetForge.Authentication Identity / Keycloak / None registration, Keycloak back-channel and role mapping, /auth/login, setup redirect
Heroicsoft.NetForge.Components Shared services (toasts, dialogs, sidebar refresh, paging maths, shell options) plus the
f- styled shell, dialogs, toasts, pager, empty states, router, and light/dark toggle. No Bootstrap.
Heroicsoft.NetForge.Components.Bootstrap The same set on Bootstrap/Bootswatch, with the Bootswatch theme picker. References Heroicsoft.NetForge.Components.
Heroicsoft.NetForge.Hangfire Administrator-only Hangfire dashboard filter

New app


<PackageReference Include="Heroicsoft.NetForge.Components.Bootstrap" Version="1.0.0" />

<PackageReference Include="Heroicsoft.NetForge.Authentication" Version="1.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="10.0.12" />

Bootstrap apps: restore Bootswatch, Bootstrap, and Bootstrap Icons into wwwroot/lib (see templates/libman.json). The theme picker swaps those stylesheets at runtime; the library does not embed them. Import Heroicsoft.NetForge.Components.Bootstrap in _Imports.razor and call AddNetForgeBootstrapComponents(ui => ui.ThemeStorageKey = "myapp.theme").

nf apps: no libman needed. Import Heroicsoft.NetForge.Components and call AddNetForgeComponents(ui => { ui.ThemeStorageKey = "myapp.theme"; ui.AccentColor = "#4f46e5"; ui.AccentColorDark = "#818cf8"; }). Never import both component namespaces in one app: the shared component names would be ambiguous.

ThemeStorageKey is the key for the default area (the public site, an empty name). A named area gets that key plus a lower-case suffix, so myapp.theme and myapp.theme.admin are remembered separately and every library on the same area follows the same choice. List the areas that should differ. Anything not listed, including the Identity UI, keeps the default area's theme. ForgeHostPage reads the route or the first path segment (/Admin/...). Set Area="Admin" when a screen lives at some other path but should still use that area, which is how LogVue or IdentityNexus can share the back-office theme from /logs or /identity. The value is a Bootswatch name, or for an nf app light, dark, or system. Null uses the app default.

builder.Services.AddCascadingAuthenticationState();
builder.Services.AddNetForgeBootstrapComponents(ui =>
{
    ui.ThemeStorageKey = "myapp.theme";
    ui.Areas["Admin"] = "darkly";
});
builder.Services.Configure<ForgeShellOptions>(shell =>
{
    shell.Brand = "My App";
    shell.SearchUrlFormat = "/?q={0}";
    shell.Sections.Add(new ForgeNavSection
    {
        Items =
        [
            new ForgeNavItem { Title = "Home", Href = "/", Icon = "bi-house", MatchAll = true },
        ],
    });
});

var auth = builder.Services.AddNetForgeAuthentication<ApplicationUser, ApplicationRole, ApplicationDbContext>(
    builder.Configuration);

var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.UseNetForgeSetupGate(); // after registering ISetupStatus, if the app has a wizard
app.MapControllers();
if (auth == AuthProvider.Identity)
{
    app.MapRazorPages();
}

Components/App.razor:

<ForgeHostPage Title="My App" IconHref="img/Icon.png" AppStylesheet="@Assets["css/site.css"]">
    <ForgeRouter AppAssembly="typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)" />
</ForgeHostPage>

Authentication:Provider is Identity, Keycloak, or None, with the same Authentication:Keycloak keys the other apps already use. None signs every request in as a single administrator and must not be exposed beyond the machine running it.

Pages inject ToastService, DialogService, and SidebarRefresh instead of copying those types. ShellLayout is the default layout: set ForgeShellOptions.Sections for a static menu, or register IShellNavigation when the sidebar is loaded from data. GetSectionsAsync is awaited on startup and again after SidebarRefresh.NotifyChanged(). A search format of /?q={0} fills the box from that query parameter and clears it when the box is submitted empty. TopbarEndComponent and SidebarFooterComponent add a bell or a pinned footer without replacing the layout. A nav item highlights a query with ActiveQuery (a null value means the parameter is absent) and can set Tooltip, Count, and TagIcon. Set NavigationPlacement to Topbar when those links belong in the header and the app should not render a sidebar.

Hangfire hosts add Heroicsoft.NetForge.Hangfire and pass new AdministratorDashboardAuthorizationFilter() in the dashboard options.

MVC hosts keep their own /auth controller and IUserContextService. Pass IncludeAuthController = false, RegisterUserContext = false, and Identity.UseRelaxedPasswordPolicy = false. Keycloak behind a reverse proxy also sets RequireHttpsMetadata = false, correlation cookies to SameSite=None / Secure=Always, and RedirectBrowserToPublicAuthority = true. Set AccessDeniedPath to /Home/AccessDenied and RemoteFailurePath to /Home/Error. When Authentication:Keycloak:PublicOrigin is set, post-logout redirects to {PublicOrigin}/signout-callback-oidc.

Blazor hosts leave those flags at their defaults and pass the app's existing theme storage key (linkstash.theme, and the same pattern in the other apps) so a stored theme survives the switch.

Left in the app

Domain pages, EF contexts, and user-directory services stay in the app. IUserInfoService and the Keycloak admin client differ once they start returning each app's own user model, so they were not pulled into the library.

Support

If you find this project useful, consider supporting its development.

<p align="center"> <a href="https://buymeacoffee.com/vnmatt"> <img src="https://github.com/gordon-matt/MyResume/blob/gh-pages/assets/images/BuyMeACoffee_Logo.png" alt="Buy Me a Coffee" height="40"> </a>    <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=gordon_matt%40live%2ecom&lc=AU&currency_code=AUD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted"> <img src="https://github.com/gordon-matt/MyResume/blob/gh-pages/assets/images/PayPal_Logo.png" alt="Donate with PayPal" height="40"> </a> </p>

<p align="center"> Prefer using your phone? Scan the QR code: </p>

<p align="center"> <a href="https://buymeacoffee.com/vnmatt"> <img src="https://github.com/gordon-matt/MyResume/blob/gh-pages/assets/images/BuyMeACoffee_QR.png" alt="Buy Me a Coffee QR Code" width="180"> </a> </p>

<img src="https://komarev.com/ghpvc/?username=gordon-matt&label=GitHub%20Hits%20Since%202025-06-01%3A%20&color=ff0000&style=flat" alt="gordon-matt" />

Product Compatible and additional computed target framework versions.
.NET 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 (3)

Showing the top 3 NuGet packages that depend on Heroicsoft.NetForge.Components:

Package Downloads
LogVue

An in-process Blazor dashboard for viewing, querying and deleting an ASP.NET Core application's logs.

Heroicsoft.NetForge.Components.Bootstrap

Bootstrap and Bootswatch implementation of the NetForge Blazor shell, theme picker, toasts, dialogs, paging, and status pages. For apps that already use Bootstrap; apps with their own styling use Heroicsoft.NetForge.Components.

IdentityNexus

A Blazor UI for administering ASP.NET Core Identity users and roles.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.1 93 10/27/2026
1.1.0 104 10/26/2026
1.0.3 135 10/23/2026
1.0.2 97 10/16/2026
1.0.1 100 10/16/2026
1.0.0 99 10/16/2026 1.0.0 is deprecated because it is no longer maintained.