Skip to content

Web Quick Start preview

Hermes.Web lets you build desktop applications using any JavaScript or TypeScript framework — React, Vue, Svelte, Angular, or vanilla JS. Instead of Blazor, your UI runs as a standard web app inside the Hermes WebView, with full access to native desktop capabilities through the interop bridge.

When to use Hermes.Web vs Hermes.Blazor

Use Hermes.Web when your team already has a JavaScript/TypeScript frontend, when you want access to the broader JS ecosystem (Vite, ESLint, Tailwind, etc.), or when migrating an existing Electron app. Use Hermes.Blazor when you prefer an all-C# stack.

Prerequisites

  • .NET 10 SDK
  • Node.js 18+ and npm (for your frontend project)
  • Platform-specific WebView requirements (see Installation)

Project Setup

Create a new console application and add the Hermes.Web package:

bash
dotnet new console -n MyDesktopApp
cd MyDesktopApp
dotnet add package Mythetech.Hermes.Web

Scaffold a frontend project inside your app directory. This example uses Vite with vanilla TypeScript, but you can use any framework:

bash
npm create vite@latest frontend -- --template vanilla-ts
cd frontend
npm install @hermes/bridge

Program.cs

Replace your Program.cs with:

csharp
using Hermes;
using Hermes.Web;

HermesWindow.Prewarm();

var builder = HermesWebAppBuilder.Create(args);

builder.ConfigureWindow(opts =>
{
    opts.Title = "My Desktop App";
    opts.Width = 1024;
    opts.Height = 768;
    opts.CenterOnScreen = true;
    opts.DevToolsEnabled = true;
});

#if DEBUG
builder.UseDevServer("http://localhost:5173");
#else
builder.UseStaticFiles("frontend/dist");
builder.UseSpaFallback();
#endif

builder.UseInteropBridge(bridge =>
{
    bridge.Register<string, string>("greet", name => $"Hello from C#, {name}!");
    bridge.Register("getRuntime", () => $".NET {Environment.Version}");
});

var app = builder.Build();
app.Run();

Frontend Code

In your frontend's main.ts, use the bridge to call C# methods:

typescript
import { bridge } from '@hermes/bridge';

const result = await bridge.invoke<string>('greet', 'World');
console.log(result); // "Hello from C#, World!"

Running in Development

Start the Vite dev server and the .NET app in separate terminals:

bash
# Terminal 1 — frontend dev server
cd frontend
npm run dev

# Terminal 2 — .NET host
dotnet run

The Hermes window opens and connects to the Vite dev server. Hot module replacement works natively — edit your frontend code and see changes instantly.

Building for Production

Build the frontend, then publish the .NET app:

bash
cd frontend
npm run build

cd ..
dotnet publish -c Release

In Release mode, Hermes serves the built assets from frontend/dist via the custom scheme handler. No dev server required.

Content Hosting

Hermes.Web provides two modes for serving your frontend content:

ModeMethodUse Case
Dev ServerUseDevServer(url)Development with HMR
Static FilesUseStaticFiles(path)Production builds

UseStaticFiles() with no argument defaults to wwwroot/. Pass a path like "frontend/dist" or "build" to match your framework's output directory.

UseSpaFallback() enables index.html fallback for client-side routing — without it, deep links return 404.

Window Options

Configure the native window through ConfigureWindow:

csharp
builder.ConfigureWindow(opts =>
{
    opts.Title = "My App";
    opts.Width = 1280;
    opts.Height = 720;
    opts.CenterOnScreen = true;
    opts.Resizable = true;
    opts.DevToolsEnabled = true;

    // Size constraints
    opts.MinWidth = 640;
    opts.MinHeight = 480;

    // Remember position/size between launches
    opts.WindowStateKey = "main-window";

    // Frameless window
    opts.Chromeless = true;
    opts.CustomTitleBar = true;
});

See the full HermesWindow API for all available options.

Next Steps