# miso > miso is a small, fast and composable Haskell library for building web and native user interfaces. Compiles to WebAssembly or JavaScript. The complete documentation of miso, from https://haskell-miso.org, as Markdown. An index of the individual pages is at https://haskell-miso.org/llms.txt --- # Introduction > What miso is, the problems it solves, and where its ideas come from. Source: https://haskell-miso.org/docs/introduction/ `miso` is a library for building web and native user interface applications. It provides a [React](https://react.dev)-like programming experience for a simple Haskell dialect that emphasises **performance**, **purity**, **simplicity**, **extensibility** and **composability**. ## What miso addresses miso covers the common areas of web development so that you can spend your time on your application: - **DOM manipulation** — miso uses a [Virtual DOM](https://en.wikipedia.org/wiki/Virtual_DOM) with a diffing algorithm that is responsible for all DOM modification and `Component` lifecycle hooks. - **Event delegation** — all event listeners are attached to a top-level element (typically ``). When raised, events are routed through the virtual DOM to Haskell handlers that change application state. Both the `capture` and `bubble` phases are virtualised. - **Prerendering** — the server delivers HTML before the JavaScript or WebAssembly bootstraps. Instead of an initial draw, the client populates the virtual DOM from the real DOM ("hydration"), which avoids a redraw and helps SEO. `Miso.Html.Render` renders on the server; `miso` hydrates on the client. - **Components** — a `Component` is a self-contained miso application bundling its state, the logic that updates it and a function that renders it. Components nest to arbitrary depth. - **Custom renderers** — the underlying DOM operations are abstracted so a different rendering engine can be plugged in. This is how [miso targets mobile devices](https://haskell-miso.org/docs/native/overview/) through Lynx. - **Lifecycle hooks** — `mount` and `unmount` on components, `onCreated` and `onDestroyed` on elements. Commonly used for component communication and third-party JavaScript integration. - **State management** — component `model` state is manipulated with `Miso.Lens` or `Miso.State`. - **HTTP / cookies** — `Miso.Fetch` wraps the Fetch API and `Miso.Cookie` the CookieStore API, each with an asynchronous callback-based `Effect` and a synchronous `_`-suffixed `IO` variant. ## Architecture - **React** — miso implements a subset of the React architecture internals: components, lifecycle hooks, virtual DOM, event delegation, along with the Fragment, Props and Context API features. - **Elm** — miso also implements the Elm architecture (model–view–update) and the `mailbox` communication pattern. ## Native (mobile) Beyond the browser, miso targets native mobile devices by driving the [Lynx](https://lynxjs.org) runtime instead of the DOM. The same MVU model, `Component` API, event delegation and virtual-DOM diffing carry over unchanged — only the element vocabulary differs. The native backend is gated behind the `native` cabal flag; web and WASM builds are unaffected. See the [native section](https://haskell-miso.org/docs/native/overview/) for the dual-thread architecture. ## Where to next - [Installation](https://haskell-miso.org/docs/installation/) — set up the WASM toolchain and build the sample app. - [Your first Component](https://haskell-miso.org/docs/your-first-component/) — the counter, line by line. - [Thinking in miso](https://haskell-miso.org/docs/thinking/overview/) — how to structure a real application. --- # Installation > Get a WebAssembly (or JavaScript) toolchain with nix and build the sample application. Source: https://haskell-miso.org/docs/installation/ miso applications compile to WebAssembly (the primary target) with the GHC WASM backend, or to JavaScript with the GHC JS backend. The quickest way to a working toolchain is the [miso flake](https://github.com/dmjio/miso/blob/master/flake.nix). ## 1. Build and serve the sampler With [nix](https://nixos.org) installed (flakes enabled), clone the [sampler](https://github.com/haskell-miso/miso-sampler) and run it — the flake provides the whole WASM toolchain (`wasm32-wasi-cabal`, `wasm32-wasi-ghc`, `http-server`, `ghciwatch`): ```shell $ git clone https://github.com/haskell-miso/miso-sampler $ cd miso-sampler $ nix develop .#wasm --command bash -c 'make all && make serve' ``` Then open [http://localhost:8080](http://localhost:8080). `make all` runs `wasm32-wasi-cabal build`, copies `static/` to `public/`, generates the JS FFI glue with `post-link.mjs` and shrinks the `.wasm` with `wasm-opt`. `make watch` starts `ghciwatch` with the WASM browser GHCi for hot reload. A JavaScript-backend shell (`javascript-unknown-ghcjs-ghc`) is available as `.#ghcjs`, and a plain GHC shell as the default. ## 2. Wire up your own project A miso executable is an ordinary cabal executable. For WASM builds it is linked as a reactor and exports `hs_start`: ``` executable app main-is: Main.hs build-depends: base, miso if arch(wasm32) ghc-options: -no-hs-main -optl-mexec-model=reactor "-optl-Wl,--export=hs_start" cpp-options: -DWASM ``` and `Main.hs` exports its entry point when compiled for WASM: ```haskell {-# LANGUAGE CPP #-} module Main where import Miso #ifdef WASM foreign export javascript "hs_start" main :: IO () #endif main :: IO () main = startApp defaultEvents app ``` The `index.js` loader instantiates the module with a WASI shim and calls `hs_start`. Copy it from the [sampler's static/ folder](https://github.com/haskell-miso/miso-sampler/tree/master/static) to begin. ## Cabal flags | Flag | Purpose | | --- | --- | | `ssr` | Enable when rendering `View`s to HTML on a server: `text` HTML-encodes and `hydrateModel` is honoured. | | `template-haskell` | Expose `Miso.Lens.TH` (`makeLenses`, `makeClassy`). | | `native` | Enable the Lynx native backend (`Miso.Native`). | | `production` | Use the minified JavaScript runtime. | --- # Your first Component > A counter: model, update, view — and how to run it with startApp or hydrate with miso. Source: https://haskell-miso.org/docs/your-first-component/ The core type of miso is `Component`. To define one, use the `component` smart constructor. Below is a simple counter. ```haskell module Main where import Miso import Miso.Lens import qualified Miso.Html.Element as H import qualified Miso.Html.Event as HE import qualified Miso.Html.Property as HP -- The four Component type parameters: -- context - the type of the global context -- props - the props inherited from the parent -- Int - the type of the Component model -- Action - the action that updates the model counter :: Component context props Int Action counter = component m u v where -- | Initial model value m :: Int m = 0 u :: Action -> Effect context props Int Action u = \case Add -> this += 1 Subtract -> this -= 1 v :: Int -> View context props Int Action v x = vfrag [ H.button_ [ HE.onClick Add, HP.id_ "add" ] [ "+" ] , text (ms x) , H.button_ [ HE.onClick Subtract, HP.id_ "subtract" ] [ "-" ] ] main :: IO () main = startApp defaultEvents counter data Action = Add | Subtract deriving (Eq, Show) ``` **Live example: The counter, running** ```haskell data CounterAction = Add | Subtract deriving (Show, Eq) counter :: Component ctx () Int CounterAction counter = component m u v where m = 0 u = \case Add -> this += 1 Subtract -> this -= 1 v n = H.div_ [ HP.class_ "row" ] [ H.button_ [ HE.onClick Subtract ] [ "−" ] , H.strong_ [] [ text (ms n) ] , H.button_ [ HE.onClick Add ] [ "+" ] ] ``` Four type parameters follow every `Component`: the global `context` (shared by the whole tree), the `props` passed by the parent, the component's own `model` and the `action` type its `update` consumes. A top-level application fixes `context` and `props` to `()`; the `App` synonym spells that out: ```haskell type App model action = Component () () model action startApp :: Eq model => Events -> App model action -> IO () ``` ## Running it We recommend `startApp` as the starting point — it sets up event listeners, performs the initial draw and assumes `` is empty. The `miso` function (and `prerender`) assume `` has already been populated by the result of `view`: instead of drawing, `miso` hydrates. If the structures do not match it falls back to drawing from scratch. ```haskell main :: IO () main = miso defaultEvents $ \uri -> counter -- hydrate a prerendered page ``` ## Doing something on mount It is possible to execute an initial action when a `Component` is first mounted with the `mount` hook (and, similarly, `unmount`): ```haskell data Action = Init | Add | Subtract main :: IO () main = startApp defaultEvents counter { mount = Just Init } update :: Action -> Effect context props Int Action update = \case Init -> io_ (consoleLog "hello world!") ... ``` > **Note:** `startApp` and `miso` always infer `context` as `()`. Use `startAppWithContext` (or `misoWithContext` when hydrating) to seed a non-trivial context — see [Context](https://haskell-miso.org/docs/context/). --- # Model–View–Update > The Elm architecture as miso implements it: a left fold over actions. Source: https://haskell-miso.org/docs/model-view-update/ The `Component` API adheres to the [Elm](https://elm-lang.org) MVU (model–view–update) interface. It is similar to a left fold over `action`s: the `model` is updated by `update` and rendered by `view`. ``` actions: Add Add Subtract │ │ │ ▼ ▼ ▼ update: 0 ───▶ 1 ───▶ 2 ───▶ 1 ───▶ ... │ │ │ │ ▼ ▼ ▼ ▼ view: ▢ ▢ ▢ ▢ (virtual DOM, diffed & patched) ``` *Every action folds into the model; every model is rendered exactly once.* - **model** — any user-defined type. An `Eq` instance is required (we recommend the derived one): miso only redraws when the model actually changed. - **view** — the templating function that constructs a new virtual DOM (or HTML when rendering on the server). It is pure: `context -> props -> model -> View`. - **update** — describes how the model evolves in response to actions raised by the application. It takes any `action`, updates the model and optionally schedules `IO`. ## Why it works Because `view` is a pure function of state, there is exactly one place where state changes (`update`) and one place where the UI is described (`view`). Effects never run inside `update` — they are *scheduled* and their results come back as new actions, so the fold never observes partial state. This is what makes miso applications easy to reason about, easy to test and trivial to prerender. Continue with [Components](https://haskell-miso.org/docs/components/) to see how many small MVU loops compose into an application, or read [Thinking in miso](https://haskell-miso.org/docs/thinking/overview/) for a guided walkthrough. --- # The View DSL > The View type, element nodes, the smart constructors in Miso.Html.Element and element lifecycle hooks. Source: https://haskell-miso.org/docs/view-dsl/ A `VNode` represents a DOM element — the most common kind of virtual DOM node. It carries a `Namespace`, a tag name, a list of `Attribute` values and a list of child `View`s. ## The View type The `View` is a rose tree of nodes, mutually recursive with `Component` through `view`: ```haskell data View context props model action = VNode Namespace Tag [Attribute model action] [View context props model action] DirectEvents | VText (Maybe Key) MisoString | VComp (SomeComponent context) | forall childProps. VCompStatic (StaticPtr (SomeStaticComponent childProps context)) childProps | VFrag (Maybe Key) [View context props model action] | VContext (context -> View context props model action) | VProps (props -> View context props model action) | VModel (model -> View context props model action) data SomeComponent context = forall model action props. (Eq context, Eq model, Eq props) => SomeComponent (Maybe Key) props (Component context props model action) ``` `VNode` and `VText` map one-to-one onto the physical DOM. `VComp` and `VFrag` are abstract (they live only in the virtual DOM). The existential `SomeComponent` is what allows embedding polymorphic components in a `View`. `VCompStatic` carries a static pointer to its constructor and is used by the [native dual-thread runtime](https://haskell-miso.org/docs/native/static-mounting/). `VContext`, `VProps` and `VModel` are not nodes at all, but *accessors*. Each wraps a function from the app-global `context`, the enclosing component's `props` or its `model` to a `View`. The function is applied and the wrapper discarded when the enclosing `View` is built or rendered, so none of the three ever reaches the diff. Build them with `vcontext`, `vprops` and `vmodel` — see [Ambient accessors](https://haskell-miso.org/docs/ambient/). ## Element nodes ```haskell VNode HTML "div" [ HP.id_ "container" ] [ "Hello, world!" ] ``` In practice you rarely construct `VNode` directly. Use the element smart constructors from `Miso.Html.Element`, which fix the namespace and tag for you: ```haskell H.div_ [ HP.id_ "container" ] [ "Hello, world!" ] H.button_ [ HE.onClick DoSomething ] [ "Click me" ] H.h1_ [ HP.className "title" ] [ text (ms pageTitle) ] ``` For elements not covered by `Miso.Html.Element`, use `node` (or its synonym `vnode`) directly: ```haskell node HTML "details" [] [ node HTML "summary" [] [ "More info" ] ] ``` SVG and MathML elements use the `SVG` and `MATHML` namespaces and are covered by `Miso.Svg.Element` and `Miso.Mathml.Element`. Unlike `VComp` and `VFrag`, a `VNode` has a one-to-one correspondence with a physical DOM element. - `node` — raw constructor — namespace, tag, attributes, children - `vnode` — synonym for `node` - `Miso.Html.Element` — every HTML element (`div_`, `span_`, `input_` …) - `Miso.Svg.Element` — SVG graphics, animation and container elements - `Miso.Mathml.Element` — MathML elements ## Lifecycle hooks Like components, elements expose lifecycle hooks: - `onBeforeCreated` - `onCreated` / `onCreatedWith` - `onBeforeDestroyed` / `onBeforeDestroyedWith` - `onDestroyed` These are useful for initialising and tearing down third-party libraries, as in this example using [highlight.js](https://highlightjs.org): ```haskell {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE MultilineStrings #-} import Miso import Miso.FFI.QQ (js) data Action = Highlight DOMRef update :: Action -> Effect context props model Action update = \case Highlight domRef -> io_ [js| hljs.highlightElement(${domRef}) |] view :: model -> View context props model Action view _ = H.code_ [ onCreatedWith Highlight ] [ """ function addOne (x) { return x + 1; } """ ] ``` As a convention, the `*With` variant of a lifecycle hook (e.g. `onCreatedWith`) provides the target `DOMRef` to the callback. ## The smart constructors, at a glance - `node, vnode` — build a `VNode` - `text, vtext` — build a `VText` — see [Text nodes](https://haskell-miso.org/docs/text/) - `component` — build a `VComp` - `fragment, vfrag, fragment_, vfrag_` — build a `VFrag` - `(+>)` — key and mount a child `Component` - `vcontext, vprops, vmodel` — build a `VContext`, `VProps` or `VModel` — see [Ambient accessors](https://haskell-miso.org/docs/ambient/) --- # Components > The Component record, composition with (+>), keys and the mount / unmount lifecycle. Source: https://haskell-miso.org/docs/components/ A `Component` bundles a model, the `update` that evolves it and the `view` that renders it — plus everything around the edges: subscriptions, lifecycle hooks, a mailbox. Components nest, forming a typed UI tree. > **Note:** Always build components with the `component` smart constructor — `component m u v` — rather than the `Component` record constructor directly. It fills every other field with sane defaults; override the ones you need with record-update syntax, e.g. `(component m u v) { subs = [...] }`. ## The record The `component` smart constructor fills in sane defaults; you override fields with record update syntax: ```haskell data Component context props model action = Component { model :: model -- initial model , hydrateModel :: Maybe (IO model) -- optional model to hydrate from (SSR) , update :: action -> Effect context props model action , view :: model -> View context props model action , useContext :: Bool -- re-render when the global context changes , subs :: [ Sub action ] -- long-running subscriptions , styles :: [ CSS ] -- dev only: append