Skip to content

v3.2.0

Latest

Choose a tag to compare

@JordanMarr JordanMarr released this 22 Jul 16:14

πŸ–₯️ One F# Codebase. Website or Native Desktop App. You Pick at Deploy Time.

v3.2.0 adds a cross-platform desktop host to the template: a tiny Photino.NET shell that runs the same ASP.NET Core server in-process and shows the same Fable.Lit client in a native window β€” WebView2 on Windows, WKWebView on macOS, WebKitGTK on Linux.

No Electron. No bundled Chromium. No code changes between web and desktop.

explorer_2xFAYP9ilM

⚑ The Headline: Web-Grade Hot Reload in a Native Window

Traditional .NET desktop UI (WPF, WinForms, Avalonia) means edit β†’ compile β†’ restart β†’ re-navigate. The desktop host inherits the web stack's dev loop instead:

# Terminal 1 - the client dev server
cd MyApp/WebLit
npm run start
# Terminal 2 - the desktop shell (hosts the server in-process)
cd MyApp/Desktop
dotnet run

Edit your F# view code, hit save, and watch the native window update in under a second. Full Fable HMR, Elmish state preserved.

πŸ“¦ What's in the Box

  • New Desktop project (~90 lines) β€” starts Kestrel in-process and opens a native window. In Release it binds a dynamic loopback port and serves the built client from wwwroot next to the exe: fully self-contained, no configuration.
  • WebApi/WebApp.fs β€” the server wiring, extracted into one parameterized builder shared by every host (web, desktop, or embedded). Your RPC implementations don't know or care which host they're running in.
  • build.cmd PackDesktop β€” publishes the desktop app + built client to .build/desktop/, ready to zip and ship.
  • Powered by Serde.FS 1.0.0-beta.4 β€” MapRpcApi now self-initializes, so hosting the RPC server in-process requires zero bootstrap ceremony. The same typed client ⇄ server contracts work identically in a browser tab and a native window.

πŸ—οΈ Bonus: AutoCAD / Revit Add-in Recipe

The same architecture β€” in-process Kestrel + a WebView showing your Fable client β€” also works embedded inside host applications like AutoCAD and Revit (2025+). That means hot-reloadable web UI in a palette or dockable pane, with typed RPC calls marshaled onto the CAD API thread.

The full pattern (lifecycle, the ExternalEvent dispatcher bridge, WebView2 gotchas) is documented in docs/cad-addin-recipe.md.

πŸš€ Getting Started

dotnet new install fable-lit-fullstack-template
dotnet new flft -n MyApp

The Desktop project is included in every new app β€” if you only want the website, just delete the folder.

πŸ“ Also in This Release

  • Fixed the README's install instructions (the short name is flft) and dev command (npm run start).
  • CatFactsBaseUrl moved into base appsettings.json so Production-environment hosts work out of the box.
  • Cross-platform notes: Windows uses the preinstalled WebView2 Runtime; Linux needs libwebkit2gtk-4.1; macOS uses the built-in WKWebView. (Debug-mode HTTPS on macOS/Linux has a
    documented workaround in the README.)

πŸ’‘ Why This Matters

The classic desktop F# dilemma: you want native deployment, but you also want a modern, fast-iterating UI stack. Now you don't choose. Start as a desktop app and become a website later (or vice versa) by changing nothing β€” WebApi, WebLit, and Shared are byte-identical between hosts. The deployment target is just a question of which ~90-line shell you run.