BlazorCodeFirst 0.1.0-preview.2
dotnet add package BlazorCodeFirst --version 0.1.0-preview.2
NuGet\Install-Package BlazorCodeFirst -Version 0.1.0-preview.2
<PackageReference Include="BlazorCodeFirst" Version="0.1.0-preview.2" />
<PackageVersion Include="BlazorCodeFirst" Version="0.1.0-preview.2" />
<PackageReference Include="BlazorCodeFirst" />
paket add BlazorCodeFirst --version 0.1.0-preview.2
#r "nuget: BlazorCodeFirst, 0.1.0-preview.2"
#:package BlazorCodeFirst@0.1.0-preview.2
#addin nuget:?package=BlazorCodeFirst&version=0.1.0-preview.2&prerelease
#tool nuget:?package=BlazorCodeFirst&version=0.1.0-preview.2&prerelease
BlazorCodeFirst
Write Blazor components as ordinary C# instead of .razor markup. A Roslyn source generator folds
each Body into RenderTreeBuilder calls at build time. At run time there is no UI tree to
interpret, no reflection, and no expression compilation.
You write this:
using BlazorCodeFirst;
using Microsoft.AspNetCore.Components;
using static BlazorCodeFirst.Html;
[Route("/notices")]
public partial class NoticePage : BodyComponentBase
{
private int _seen;
protected override View Body =>
Div.Class("notice")[
H2["Release notes"],
P["Nothing new today."],
Button.OnClick(() => _seen++)[$"Seen {_seen} times"]];
}
The generator emits this, and it is what ships:
partial class NoticePage
{
protected override void RenderView(global::Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
{
__builder.OpenElement(0, "div");
__builder.AddAttribute(1, "class", "notice");
__builder.AddMarkupContent(2, "<h2>Release notes</h2><p>Nothing new today.</p>");
__builder.OpenElement(3, "button");
__builder.AddAttribute(4, "onclick", global::Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this, () => _seen++));
__builder.AddContent(5, $"Seen {_seen} times");
__builder.CloseElement();
__builder.CloseElement();
}
}
What the pair shows:
H2andPare both static, so they collapsed into a singleAddMarkupContentframe.- The sequence numbers are literals the generator assigned, not values counted while rendering.
NoticePageis an ordinaryComponentBasedescendant, so Blazor diffs it exactly as it diffs a Razor component, and it stays trimming-safe and AOT-safe.
The vocabulary mirrors HTML
Elements are C# helpers named after their tags. Attributes and events sit next to the tag in a
decoration chain, children follow in brackets, and layout is left entirely to CSS. That puts
BlazorCodeFirst in the lineage of kotlinx.html, Scalatags, Feliz and hiccup rather than SwiftUI or
Jetpack Compose. There are no VStack / HStack / Grid containers, and no typed .Padding() /
.FontSize() decorations.
Body is a typed C# expression, so the compiler checks names and types, and refactorings propagate
through it. What C# cannot check is the shape of a Body:
- a component that forgets
partial - state mutated inside
Body - a decoration applied to something that is not a single element
- a duplicate attribute
- a non-constant tag name
The analyzers report those as BCF**** diagnostics during the build.
Requirements
.NET SDK 10.0.100 or later, and a net10.0 Blazor project. The generator ships as a Roslyn 5.0
analyzer, so an older compiler refuses to load it. In an IDE, that means Visual Studio 2026 version
18.0 or later.
Installation
dotnet add package BlazorCodeFirst --prerelease
This is a prerelease, which is what --prerelease is for: without it the command resolves the
latest stable version instead, of which there is none. The surface is deliberately narrow and grows
one issue at a time. The single package carries both halves: the runtime in lib/net10.0, and the
generator and analyzers in analyzers/dotnet/cs.
Documentation
- Documentation site: getting started, elements and decorations, control flow, layouts. The site is itself written in BlazorCodeFirst.
- Repository: the design overview
(
DESIGN.md), the compilation algorithm and the diagnostic table (ARCHITECTURE.md), and the issue tracker.
License
MIT.
| Product | Versions 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. |
-
net10.0
- Microsoft.AspNetCore.Components (>= 10.0.11)
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.1.0-preview.2 | 72 | 8/21/2026 |