Open your app in a desktop window
You'll open an ordinary FSR app in a native window, name the window and choose how the window reaches the host. The pages, loaders and islands are the ones a browser gets. The window is the system webview: WebKit on macOS and Linux, WebView2 on Windows.
Desktop mode is experimental. It has been tried on macOS only. The Windows and Linux code is written but has not been built or run. Packaging and signing do not exist yet, so there is no app bundle to hand to someone else.
Before you start
Install from crates.io. You need no Node and no package manager.
cargo install snapfire_compiler
cargo install snapfire_fsr_cli
fsr --version
Every command and screenshot on this page was captured with fsr 0.x.
Install the desktop build#
The window is behind the desktop feature. Install the CLI with it:
Without the feature, fsr serve and fsr dev have no --desktop flag. With it, fsr serve --help lists it:
Build a small shop#
Scaffold an app with React:
Give it a product list and an about page. The products are a module constant:
;The root loader returns them and titles the page with meta:
;
;
;;
The about page has a title of its own:
;
;
Link the two from the layout:
;
;
Give the app a fixed port with [server] listen = "127.0.0.1:3402" in config/app.toml, then run it in a browser first with fsr build shop/app and fsr serve shop/app. Open http://127.0.0.1:3402/ and the tab reads Products. Click About and it reads About. That is the same app the window will show.
Name the window#
Add a [desktop] section to the configuration:
[]
= "Shop"
[]
= "Shop"The window's title is the name, a dash and the page's <title>. On the root it reads Shop - Products. On /about it reads Shop - About. A page whose title is empty or is the name itself gets the name alone, Shop. Without name, the window takes the project directory's name.
fsr check reads the section along with the rest of the configuration:
It prints nothing when the configuration loads.
Open the window#
Build the app, then serve it in a window:
fsr serve --desktop binds an ephemeral port on 127.0.0.1, opens the window once the port answers and exits when you close the window. Pass --listen to pick the port yourself:
While you work on the app, use the dev loop instead:
The dev loop owns the window, so the window stays open across rebuilds and server restarts. Save a page and the window reloads it the way a browser tab does. The window opens on [server] listen, so that needs a fixed port. Closing the window stops the loop the way Ctrl-C does.
On macOS the window has a menu bar. The Shop menu holds Quit (⌘Q). Edit holds undo, redo and the clipboard. History holds Back (⌘[), Forward (⌘]) and Reload (⌘R). A two-finger swipe goes back and forward.
Serve the window without a port#
By default the window loads the host over loopback, so any program on the machine can reach that port too. serve = "scheme" serves the window from app://localhost through the host in the same process instead, with no port at all:
[]
= "Shop"
= "scheme"
= "disk"The origin is the same on every launch, so the page's storage survives a restart. serve takes loopback or scheme. Any other value stops the build:
The webview takes each scheme response whole and keeps none of its cookies, which costs you a few things:
- A route behind
loading.tsxarrives whole once its slowest loader finishes. - Live topics and sockets do not connect.
fsr dev --desktopstays on loopback whateverservesays, so development refresh keeps working.- FSR keeps the cookies for the window itself. With the default they last the run. With
cookies = "disk"they are kept in~/Library/Application Support/Shop/cookies.jsonon macOS, readable by you alone.
There is no port under the scheme, so fsr serve shop/app --desktop refuses --listen with it.
Find what the scheme would slow down#
fsr doctor reports a route that streams under a scheme window. Add a route with a loading boundary:
;
;
Build and ask the doctor:
Remove serve = "scheme" to keep streaming. Keep it when no port matters more to you. Without the orders route the doctor reports 22 checks, nothing to report.
Next up: 710. Open a file from the desktop app.