Blazor Quick Start
Hermes provides first-class Blazor integration through the Hermes.Blazor package. This guide shows you how to build a Blazor desktop application.
Project Setup
Create a new Blazor project:
bash
dotnet new blazor -n MyBlazorApp --interactivity None
cd MyBlazorApp
dotnet add package Hermes.BlazorOr use the Hermes template:
bash
dotnet new hermes-blazor -n MyBlazorAppUpdate Program.cs
Replace your Program.cs with:
csharp
using Hermes;
using Hermes.Blazor;
using MyBlazorApp;
// Optional: Pre-warm WebView for faster startup (Windows)
HermesWindow.Prewarm();
var builder = HermesBlazorAppBuilder.CreateDefault(args);
builder.ConfigureWindow(options =>
{
options.Title = "My Blazor App";
options.Width = 1024;
options.Height = 768;
options.CenterOnScreen = true;
options.DevToolsEnabled = true;
});
builder.RootComponents.Add<App>("#app");
var app = builder.Build();
app.Run();Update App.razor
Ensure your App.razor has a root element with id app:
razor
<!DOCTYPE html>
<html>
<head>
<title>My Blazor App</title>
<link href="css/app.css" rel="stylesheet" />
</head>
<body>
<div id="app">
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" />
</Found>
<NotFound>
<h1>Page not found</h1>
</NotFound>
</Router>
</div>
<script src="_framework/blazor.web.js"></script>
</body>
</html>Adding Menus
Access the main window through the app builder:
csharp
var app = builder.Build();
// Configure menus
app.MainWindow.MenuBar
.AddMenu("File", file =>
{
file.AddItem("New", "file.new", item => item.WithAccelerator("Ctrl+N"))
.AddSeparator()
.AddItem("Exit", "file.exit", item => item.WithAccelerator("Alt+F4"));
})
.AddMenu("Edit", edit =>
{
edit.AddItem("Cut", "edit.cut", item => item.WithAccelerator("Ctrl+X"))
.AddItem("Copy", "edit.copy", item => item.WithAccelerator("Ctrl+C"))
.AddItem("Paste", "edit.paste", item => item.WithAccelerator("Ctrl+V"));
});
app.MainWindow.MenuBar.ItemClicked += itemId =>
{
if (itemId == "file.exit")
{
app.MainWindow.Close();
}
};
app.Run();Dependency Injection
Register services as you would in any Blazor app:
csharp
builder.Services.AddSingleton<IMyService, MyService>();
builder.Services.AddScoped<IScopedService, ScopedService>();Access them in your components:
razor
@inject IMyService MyService
<h1>@MyService.GetGreeting()</h1>Window Options
Configure the window through ConfigureWindow:
csharp
builder.ConfigureWindow(options =>
{
// Basic settings
options.Title = "My App";
options.Width = 1024;
options.Height = 768;
// Positioning
options.CenterOnScreen = true;
// Or specific position:
// options.X = 100;
// options.Y = 100;
// Size constraints
options.MinWidth = 640;
options.MinHeight = 480;
// Behavior
options.Resizable = true;
options.DevToolsEnabled = true;
options.ContextMenuEnabled = false;
// Custom title bar (for frameless windows)
options.CustomTitleBar = true;
// Remember window position/size between launches
options.WindowStateKey = "main-window";
});macOS Dock Menu
On macOS, you can add items to the dock menu:
csharp
if (HermesApplication.DockMenu is { } dockMenu)
{
dockMenu
.AddItem("New Window", "dock.new")
.AddSeparator()
.AddSubmenu("Recent", "dock.recent", recent =>
{
recent.AddItem("File1.txt", "recent.1")
.AddItem("File2.txt", "recent.2");
});
dockMenu.ItemClicked += itemId =>
{
Console.WriteLine($"Dock menu clicked: {itemId}");
};
}Communicating with JavaScript
Send messages to JavaScript:
csharp
app.MainWindow.SendMessage("Hello from C#!");Receive messages from JavaScript:
csharp
app.MainWindow.OnWebMessage(message =>
{
Console.WriteLine($"Received: {message}");
});In your HTML/JavaScript:
javascript
// Send to C#
window.chrome.webview.postMessage("Hello from JS!");
// Receive from C#
window.chrome.webview.addEventListener("message", (e) => {
console.log("Received:", e.data);
});Complete Example
csharp
using Hermes;
using Hermes.Blazor;
using Microsoft.Extensions.DependencyInjection;
using MyBlazorApp;
HermesWindow.Prewarm();
var builder = HermesBlazorAppBuilder.CreateDefault(args);
builder.ConfigureWindow(options =>
{
options.Title = "My Blazor App";
options.Width = 1024;
options.Height = 768;
options.CenterOnScreen = true;
options.DevToolsEnabled = true;
options.WindowStateKey = "main";
});
// Register services
builder.Services.AddSingleton<IAppState, AppState>();
// Add root component
builder.RootComponents.Add<App>("#app");
var app = builder.Build();
// Configure menus
app.MainWindow.MenuBar
.AddMenu("File", file =>
{
file.AddItem("Exit", "file.exit", item => item.WithAccelerator("Ctrl+Q"));
})
.AddMenu("Help", help =>
{
help.AddItem("About", "help.about");
});
app.MainWindow.MenuBar.ItemClicked += itemId =>
{
if (itemId == "file.exit") app.MainWindow.Close();
};
app.Run();Next Steps
- Menus Guide — Advanced menu patterns
- Dialogs Guide — File and folder dialogs
- WebView Interop — C# to JavaScript communication
