Skip to content

Repository files navigation

Vidra

Build cross-platform desktop apps with React, Vue, or Svelte on a C#/.NET native layer.

The type-safe, lightweight alternative to Electron (Node), Tauri (Rust), and XAML (MAUI · Avalonia · WPF).

Quick Start · Documentation · Architecture · Capabilities

create-vidra-app on npm @vidra-dev/sdk on npm License: MIT


Vidra lets .NET teams build cross-platform desktop applications with any modern web framework on a native C#/.NET core. The UI is pure web ( React, Vue, Svelte, Solid, your call ) the native layer is C#, and a type-safe bridge generated from your C# code keeps the two sides permanently in sync. Unlike Electron you never touch Node; unlike Tauri you never touch Rust; unlike MAUI, Avalonia, or WPF you never touch XAML.

Alpha. APIs and templates may change between 0.x releases.

Why Vidra

  • Stay in C#/.NET. Your native layer, domain logic, and NuGet libraries are all C#. No second backend language for the team to learn.
  • Bring any web framework. The UI is a standard web app rendered in a native WebView: React, Vue, Svelte, Solid, or plain HTML. No XAML, no Razor lock-in.
  • End-to-end typed contracts. Native methods, event contracts, and JS contracts are declared in C#; generated C#/TypeScript surfaces and startup fingerprints prevent silent drift. Dynamic traffic remains available only through an explicit unsafe escape hatch.
  • Lightweight. Uses the OS-native WebView (WKWebView / WebView2) instead of bundling Chromium, keeping apps small and memory-light.
  • One bridge, both ways. Native calls, event contracts, and JS contracts all flow over one versioned JSON bridge.

Quick Start

The fastest way to start is the create-vidra-app scaffolder:

npm create vidra-app@latest

You'll be prompted for a project name and an app ID (reverse-domain). Then launch it:

cd my-app
npm run dev

npm run dev (which runs vidra dev) starts Vite and the native host for your current OS together, with Vite HMR and a C# loop: supported edits hot reload into the running app. On macOS the Mac Catalyst hot-reload agent sometimes drops out mid-session (dotnet/sdk#55488); when it does, vidra dev says so and keeps the loop working by rebuilding and relaunching on save.

Prerequisites

  • .NET 10 SDK
  • The .NET MAUI workload: dotnet workload install maui
  • Node.js 18+
  • macOS targets require Xcode; Windows targets must be built on Windows

Not sure you're set up? Run npm run doctor to check your .NET SDK, MAUI workload, and (on macOS) Xcode, and print the exact command to fix anything missing.

The vidra CLI

The vidra CLI is a local dev dependency of each scaffolded app — there's no global vidra to install. Run it from inside your project via the npm scripts or npx:

npm run dev                     # start Vite + native host (UI + C# reload on save)
npm run build                   # build + package for distribution
npm run doctor                  # verify your environment
npx vidra run                   # launch the native host only
npx vidra dev --target windows  # run a specific desktop target
npx vidra build --target macos  # build & package a specific target

Add --plan to any build to preview every step and the artifact name without running anything.

Shipping to other machines

vidra build produces a macOS .dmg or a self-contained Windows .zip. Both run locally as-is, but an app that arrives over the internet also has to satisfy the OS: macOS wants a Developer ID signature plus notarization, Windows wants an Authenticode signature. Configure them by environment and vidra build does the rest — with nothing configured it still builds, it just warns and skips.

Variable Purpose
VIDRA_MACOS_CODESIGN_KEY Force a specific macOS signing identity (otherwise a Developer ID Application certificate is preferred for builds)
VIDRA_NOTARY_PROFILE notarytool keychain profile — enables notarization + stapling
VIDRA_APPLE_ID / VIDRA_TEAM_ID / VIDRA_APP_PASSWORD Notarization credentials, as an alternative to a stored profile
VIDRA_WINDOWS_CERT_PATH / VIDRA_WINDOWS_CERT_PASSWORD Authenticode certificate file
VIDRA_WINDOWS_CERT_THUMBPRINT Authenticode certificate already in the Windows store
VIDRA_WINDOWS_TIMESTAMP_URL Timestamp server (defaults to DigiCert)

npm run doctor reports which of these are in place. The macOS build signs with the hardened runtime using the Entitlements.plist in your host project — those entitlements are what keep .NET's JIT alive under it, so keep them.

Windows note: the ZIP bundles the .NET runtime and the WindowsAppSDK, but the WebView2 runtime is a machine-wide install. It ships with Windows 11 and alongside Edge on Windows 10; a machine without it shows a blank window.

How it works

A single WebView hosts your web UI; the .NET MAUI host owns all native capability. Calls flow JS → C# as JSON requests over a native message channel (with a custom-scheme fallback), while responses, event contracts, and JS contracts flow back over the same bridge. Protocol v2 addresses all traffic by contract/member and verifies generated core and app manifest fingerprints when the WebView starts.

See Architecture for the full diagram and host model, and Interop Protocol for the wire format.

Type safety via codegen

Native modules are plain C# classes; event and JS contracts are C# interfaces. Their payload/result records define every safe cross-language operation:

[BridgeModule("filesystem")]
public sealed class FileSystemModule : BridgeModuleBase
{
    [BridgeMethod("readText")]
    public async Task<ReadTextResult> ReadTextAsync(ReadTextArgs args, CancellationToken ct)
        => new(await File.ReadAllTextAsync(args.Path, ct));
}

[JsContract("counter")]
public interface ICounterJs
{
    [JsMethod("increment")]
    Task<int> IncrementAsync();
}

During compilation, a Roslyn generator emits AOT-safe event tokens, Bridge.Js() clients, codecs, and diagnostics. After compilation, vidra-codegen emits matching TypeScript native/event proxies and JS-handler registries:

import { filesystem } from "@vidra-dev/sdk";
import { counterHandlers } from "./generated/index.js";

// `path` is required and typo-checked; `content` is inferred as `string`.
const { content } = await filesystem.readText({ path: "/tmp/notes.txt" });
counterHandlers.increment(() => 1);

Full pipeline and C# → TS type mapping: Type safety & codegen →

Documentation

Page What's inside
Architecture Host model, bridge design, and the codegen pipeline
Interop Protocol JSON envelopes, transports, and error codes
Capabilities Every built-in module and its typed methods
Testing How the bridge and codegen output are tested

Packages

Package Description
create-vidra-app Scaffolder + the vidra CLI (dev / run / build / doctor)
@vidra-dev/sdk Framework-agnostic runtime plus generated native/event proxies

Targets

Platform Status
Windows Supported
macOS Supported

Mobile (iOS / Android) is on the roadmap as the .NET MAUI foundation makes it a natural next target.

Contributing

Contributions are welcome! To get started:

  1. Fork the repo and create a branch from main.
  2. Make your change — for anything non-trivial, consider opening an issue first to discuss the approach.
  3. Run the relevant test suites (see Testing for how to run them locally).
  4. Open a pull request with a short description of what changed and why.

License

MIT · Report an issue →

About

Build cross-platform desktop apps with React, Vue, or Svelte on a C#/.NET native layer. Vidra is type-safe, lightweight alternative to Electron (Node), Tauri (Rust), and XAML (MAUI/Avalonia/WPF).

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages