Getting started
Quick Start
Go from an empty folder to a C# app that renders on the server, hydrates in the browser and reloads as you edit. Four commands and one new file.
Already have .NET? Here is the whole thing:
$ dotnet new install Natrix.Templates$ dotnet new natrix -o MyApp$ cd MyApp$ dotnet watch --project MyAppPrerequisites
You need the .NET SDK, and nothing from the JavaScript world: no Node.js, no npm and no Tailwind CLI. Tailwind runs inside the C# compiler.
.NET SDK 9 or 10
Natrix targets both. The template defaults to .NET 10.
dotnet --versionA trusted HTTPS certificate
The app serves on https://localhost. Trust the ASP.NET Core development certificate once per machine.
dotnet dev-certs https --trustwasm-tools (optional)
Not needed to develop. Install it when you publish with AOT compilation (RunAOTCompilation).
dotnet workload install wasm-toolsDon't have the SDK yet? Download .NET for Windows, macOS or Linux.
Create your app
Install the template
Natrix ships its project template as a NuGet package. Install it once; it stays available to
dotnet newfrom then on.$ dotnet new install Natrix.TemplatesTo get a newer template later, run
dotnet new update.Create a project
This creates a
MyAppfolder with two projects in it: a server that renders HTML and a WebAssembly client that takes over in the browser. Pick any name; it becomes the namespace too.$ dotnet new natrix -o MyAppTargeting .NET 9?
Add
-F net9.0to the command. The template defaults tonet10.0.Run it
dotnet watchbuilds both projects, starts the server and opens your browser. The first build restores packages and compiles the client, so give it a minute.$ cd MyApp$ dotnet watch --project MyApphttps://localhost:5100MyAppHomeAboutBuild with Natrix
This project was generated with the natrix template and includes server-side rendering, hydration, routing, and Tailwind CSS.
Click About in the header: the page changes without a reload. The first view came from the server as plain HTML; everything after it runs in .NET in your browser.
Prefer a plain run?
dotnet run --project MyAppstarts the same app without watching for changes. The template also includes VS Code launch and build settings.Add a page
A page is a component: a class whose
Setupmethod runs once and returns the elements to show. Add a counter page to the client project.MyApp.Client/Components/CounterPage.csusing Natrix.Core.Components; using Natrix.Dom.Components; using Natrix.Signals; namespace MyApp.Client.Components; public class CounterPage : BaseComponent<NoProps, NoEvents, NoSlots, NoExpose> { protected override IComponent[] Setup(out NoExpose exposed) { exposed = default; // Setup runs once. After that, only what reads `count` updates. var count = new Signal<int>(0); return [ new Section { Props = new SectionProps { Class = "max-w-3xl mx-auto px-4 sm:px-8 py-12".ToConstSignal(), }, Children = [ new P { Props = new PProps { Class = "text-6xl font-bold tabular-nums".ToConstSignal(), }, Children = [new DomText { Text = new Computed<string>(() => $"{count.Value}") }], }, new Button { Props = new ButtonProps { Class = "mt-6 rounded-lg bg-indigo-600 px-5 py-2.5 font-semibold text-white hover:bg-indigo-500".ToConstSignal(), }, Events = new ButtonEvents { OnClick = _ => count.Value++ }, Children = [new DomText { Text = "Click me".ToConstSignal() }], }, ], }, ]; } }Give it a route in
App.cs, next to the two that are there,MyApp.Client/Components/App.cs// Add to the Items of Routes: new Route { Pattern = "/counter", Render = () => [new CounterPage { Props = new NoProps() }], },and a link in the header, in
NavItems.cs:MyApp.Client/Components/NavItems.csinternal static readonly NavItem[] All = [ new("Home", "/"), new("About", "/about"), new("Counter", "/counter"), // new ];Save, and
dotnet watchpicks it up. Open Counter and click: the number updates and nothing else on the page is touched. Now change"Click me"or a class name and save again; the change appears in the open tab without a refresh.Where Tailwind looks for classes
The stylesheet is built from the class names written in plain string literals in the client project. Write each class out in full, like
bg-indigo-600, in a string that isn't interpolated, and keep the components that use them inMyApp.Client.
What's in the project
Two projects that share one set of components. The client holds your pages; the server references it and renders those same components to HTML, so a page is written once and runs in both places.
Troubleshooting
dotnet new can't find a template called natrix
The template isn't installed for the SDK you're running. Run dotnet new install Natrix.Templates again, then check with dotnet new list natrix.
The browser says the connection isn't private
The development certificate isn't trusted yet. Run dotnet dev-certs https --trust, then restart the app and the browser.
Port 5100 is already in use
Change applicationUrl in MyApp/Properties/launchSettings.json to a free port.
A Tailwind class has no effect
Tailwind only generates the classes it finds in plain string literals in the client project. Classes in an interpolated string, like $"px-4 {extra}", classes put together at runtime, and classes named only in the server project are never seen. Write them out in full in a plain string in MyApp.Client.
Moving an existing app to a newer Natrix
Change the versions in Directory.Packages.props. The three Natrix packages are released together, so keep them on the same version.
Next steps
Each example runs live on this site, with its source a click away. Read them in any order.