miso

Native (mobile)

miso native

Miso.Native targets native mobile devices by driving the Lynx runtime instead of the browser DOM. The same MVU programming model, Component API, event delegation and virtual-DOM diffing you use on the web carry over unchanged — only the element vocabulary differs (view_, text_, … instead of div_ / span_) and rendering is performed by Lynx's element PAPI rather than by mutating a browser DOM.

This module is the native analogue of the miso / startApp entry points: native (and nativeWithContext) boot a root component onto the Lynx runtime.

Anatomy of a native miso app

Keep scrolling — the phone comes apart into the dual-thread architecture that runs miso on iOS and Android.

miso
iOS process
PrimJSmain threadMTS
PrimJSbackground threadBTS
main.lynx.bundle
JSCSSassets
main.lynx.bundle
JSCSSassets
GHC RTSGHC RTS
your application — model · update · view
miso

A miso app on your phone.

It all lives in one iOS process.

Lynx hosts two JavaScript interpreters: the main thread renders, the background thread thinks.

Each interpreter loads the same bundle — JavaScript, CSS, assets.

And inside the JS: two GHC runtimes, one application, one miso.

scroll

Enabling native

The native backend is gated behind the native cabal flag. It must be enabled to bring Miso.Native and the Miso.Native.* element / event / FFI modules into scope (build with -fnative). Web / WASM builds are unaffected — all cross-thread machinery lives behind the NATIVE CPP guard.

$ nix develop github:dmjio/miso#native
$ cabal build --with-compiler=javascript-unknown-ghcjs-ghc \
              --with-hc-pkg=javascript-unknown-ghcjs-ghc-pkg -f native

The JavaScript output is bundled for Lynx with rspeedy and loaded by the Lynx Explorer app or your own iOS / Android shell. The miso-lynx repository has the tooling and a gallery.

Building a bundle with Nix

miso's flake exports everything needed to produce a main.lynx.bundle reproducibly. miso.lib.${system}.ghcNative is the GHC-JS package set with miso-native preinstalled — callCabal2nix your own app into it — and pkgs.mkLynxBundle (also exported as miso.lib.${system}.mkLynxBundle) turns that JS derivation into a Lynx bundle:

{
  inputs.miso.url = "github:dmjio/miso";

  outputs = { miso, ... }:
    let system = "aarch64-darwin";                  # or x86_64-linux, …
        lib = miso.lib.${system};
    in {
      packages.${system}.bundle = lib.mkLynxBundle {
        name    = "my-app-bundle";
        jsDrv   = lib.ghcNative.callCabal2nix "my-app" ./. { };
        exeName = "my-app";
        styles  = ./styles.css;
      };
    };
}

nix build .#bundle then leaves result/main.lynx.bundle ready to load in the Lynx Explorer app. For interactive work, nix develop github:dmjio/miso#native provides the GHC-JS compiler (the ghcNative package set), rspeedy and bun.

To ship a standalone iOS app, the miso-lynx-gallery example includes an ios/ folder: copy the bundle the Nix derivation produced (the /nix/store output symlinked at ./result) into the assets in ios/ and build with Xcode. See miso-lynx-gallery for more information.

The UI stack miso drives natively, in the flesh — screens from Lynx's example apps. The miso-lynx-gallery repository builds a gallery of these components in miso.

In this section