RazorClassBlog 0.0.7

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

RazorClassBlog

A lightweight, embeddable blog system for ASP.NET Core Razor Pages, delivered as a Razor Class Library (RCL).


About this project

RazorClassBlog exists to solve a very specific problem:

"I need a simple, SEO-friendly blog inside my existing ASP.NET Core site - not a full CMS, not a headless platform, and not a WordPress clone."

This project provides:

  • Public blog pages that search engines can crawl and index
  • An optional admin UI for managing posts
  • Clean architecture that lets the host application control authentication, identity, and data storage

It is designed to be:

  • Embedded, not hosted
  • Configurable, not opinionated
  • Small, not over-engineered

If you want a full CMS, this probably isn't it. If you want a blog that "just works" inside your app, it might be.

This was also a practical test to try an use AI (GPT5) to develop as much out of the box without tinkering as possible. So far its about 80% AI written, and 20% cleanup/re-structure.


Features

Public blog

  • Blog index with pagination
  • Individual post pages
  • SEO-friendly URLs (/blog/yyyy/mm/slug)
  • Breadcrumb navigation (HTML + JSON-LD)
  • Canonical URLs and meta descriptions
  • Structured data (BlogPosting / Article)
  • Open Graph & Twitter Card metadata

Admin UI (optional for a public facing side, can be turned off)

  • Create, edit, and delete posts
  • Draft, published, and scheduled posts
  • Publish scheduling (future dates)
  • Autosave drafts
  • Rich text editor (TinyMCE) (must include separately)
  • Role-based access using ASP.NET Core Identity

Architecture

  • Razor Class Library (RCL)
  • Razor Pages UI
  • Repository + service abstractions
  • Entity Framework Core-based persistence
  • Host-controlled database provider (SQL, Cosmos DB, etc.)

Technology

  • Target framework: .NET 9
  • UI: Razor Pages + Bootstrap
  • Data: Entity Framework Core
  • Auth: ASP.NET Core Identity
  • Editor: TinyMCE via Host site package (must include separately)

Installation

dotnet add package RazorClassBlog

Or reference the project directly during development.


Basic setup

Database configuration

The library depends on an IBlogDbContext abstraction. The host application supplies the concrete EF Core implementation.

Example (SQL DB):

builder.Services.AddDbContext<SQLBlogDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("BloggingDatabase")));

Example (Cosmos DB):

builder.Services.AddDbContext<CosmosBlogDbContext>(options =>
    options.UseCosmos(
        builder.Configuration["Cosmos:ConnectionString"],
        builder.Configuration["Cosmos:DatabaseName"]));

Register services

Most of the configuration happens during service registration. Ensure you pass the IBlogDbContext abstraction object context in that you used for DbContext:

builder.Services.AddBlogging<CosmosBlogDbContext>(options =>
{
  options.BlogKey = "main";       // default; change if you plan on having multiple blogs in one database
  options.PublicPageSize = 10;    // default; change if you want to show more per page on the public facing side
  options.AdminPageSize = 20;     // default; change if you want to show more per page in the admin facing side

  options.DefaultOrganizationName = "Acme Aces";                                        //what is the name of the organization this blog exists for?
  options.DefaultOrganizationImageURL = "https://cdn.AcmeAces.com/acme-aces-logo.png";  //what is the organization home page image for seo reference?

  options.AdminRoles = new[] { "Admin", "BlogAdmin" };  // default "Administrator"; change to fit your identity setup, leave blank for no auth checks
  options.ReaderRoles = new[] { "User", "Customer" };   // default empty; change to fit your identity setup, leave blank for no auth checks

  //options.EnableAdminUi = false;                      // Disable admin UI on public-only sites. Useful if you have separate sites for admin and public

  //options.BlogDescription = "News, updates, and tips from Our Company.";                                                  // default; change if you want the description on the blog/index page
  //options.BlogReason = "We share product updates, how-tos, and best practices to help you get more out of our platform."; // default; change if you want the reason on the blog/index page (can be html)

  //options.PublicRoutePrefix = "/blog";     // default; change if you want a different public blog route
  //options.PublicDisplayName = "Blog";      // default; change if you want a different public blog name
});

Ensure Razor Pages, Identity, and Authorization are enabled:

builder.Services.AddRazorPages();
builder.Services.AddAuthorization();

Middleware:

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

Admin UI & security

Admin pages

Admin pages live under:

/BlogAdmin

Access is controlled via ASP.NET Core Identity roles configured in BlogOptions.

Disable admin UI entirely

If the admin UI is hosted in a separate site, routes can be removed entirely:

options.EnableAdminUi = false;

When disabled:

  • Admin routes are not registered
  • /BlogAdmin returns 404
  • No admin surface exists to attack

Customize the public routing entirely

You can configure the public facing side to have custom names for the routes now:

options.PublicRoutePrefix = "/articles";
options.PublicDisplayName = "Articles";

When used the public blog will be accessible at /articles instead of /blog, and the display name will be "Articles" instead of "Blog". But all other functionality remains the same, items such as

<a asp-page="Index" asp-area="Blog">@Options.Value.PublicDisplayName</a>

Will now render as:

<a href="/articles">Articles</a>

Useful if you want to have a name other than blog for your site.


Publishing model

  • Draft: not visible publicly
  • Published: visible immediately
  • Scheduled: visible when PublishedUtc <= UtcNow

Author handling

Posts support an editable display author:

  • AuthorId: internal identifier (audit)
  • AuthorName: displayed author (person or organization)

Examples:

  • "Jane Doe"
  • "Acme Marketing Team"

Non-goals

This project intentionally does not attempt to be:

  • A full CMS
  • A headless content platform
  • A page builder
  • A replacement for WordPress, Ghost, or similar systems

License

MIT License


Product Compatible and additional computed target framework versions.
.NET 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 was computed.  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
0.0.7 284 12/18/2025
0.0.6 279 12/16/2025
0.0.5 241 12/15/2025
0.0.4 248 12/15/2025
0.0.3 238 12/15/2025
0.0.2 231 12/15/2025
0.0.1 126 12/12/2025

Updated app to support a function to export blog posts for SEO processing.