miso: A tasty Haskell front-end web framework

[ bsd3, data-structures, library, miso, web ] [ Propose Tags ] [ Report a vulnerability ]

Miso is a small, production-ready, component-oriented, isomorphic Haskell front-end web and mobile framework featuring a virtual-dom, recursive diffing / patching algorithm, event delegation, event batching, SVG, Server-sent events, Websockets, type-safe servant-style routing and an extensible Subscription-based subsystem. Inspired by Elm and React. Miso is pure by default, but side effects can be introduced into the system via the Effect data type. Miso makes heavy use of the GHC FFI and therefore has minimal dependencies.


[Skip to Readme]

Flags

Manual Flags

NameDescriptionDefault
benchmark

When enabled this outputs (in milliseconds) the time it takes to build the virtual DOM on page load.

Disabled
production

Uses miso's production quality JS (miso.prod.js). This is built from calling "bun build --production"

Disabled
ssr

Used to indicate if SSR (server-side rendering) is being used. Defaults to false. Enable when performing hydration / server rendering of Html using ToHtml.

Disabled
template-haskell

Checks if template-haskell is enabled. If so, allows Miso.Lens.TH

Disabled

Use -f <flag> to enable a flag, or -f -<flag> to disable that flag. More info

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

Versions [RSS] 0.1.0.0, 0.1.0.1, 0.1.0.2, 0.1.0.3, 0.1.0.4, 0.1.1.0, 0.1.2.0, 0.1.3.0, 0.1.4.0, 0.1.5.0, 0.2.0.0, 0.2.1.0, 0.3.0.0, 0.4.0.0, 0.5.0.0, 0.6.0.0, 0.7.0.0, 0.7.1.0, 0.7.2.0, 0.7.3.0, 0.7.4.0, 0.7.5.0, 0.7.6.0, 0.7.7.0, 0.7.8.0, 0.8.0.0, 0.9.0.0, 0.10.0.0, 0.11.0.0, 0.12.0.0, 0.13.0.0, 0.14.0.0, 0.15.0.0, 0.16.0.0, 0.17.0.0, 0.18.0.0, 0.19.0.0, 0.20.0.0, 0.20.1.0, 0.21.0.0, 0.21.1.0, 0.21.2.0, 1.0.0.0, 1.1.0.0, 1.2.0.0, 1.3.0.0, 1.4.0.0, 1.5.0.0, 1.5.1.0, 1.5.2.0, 1.6.0.0, 1.7.0.0, 1.7.1.0, 1.8.0.0, 1.8.1.0, 1.8.2.0, 1.8.3.0, 1.8.4.0, 1.8.5.0, 1.8.6.0, 1.8.7.0, 1.9.0.0, 1.10.0.0, 1.11.0.0, 1.12.0.0 (info)
Dependencies base (<5), bytestring (<0.13), containers (<0.9), ghc-experimental, ghcjs-base, ghcjs-prim, mtl (<2.4), template-haskell (>=2.21 && <2.25), text (<2.2), transformers (<0.7) [details]
License BSD-3-Clause
Copyright Copyright (c) 2016-2026 David M. Johnson
Author David M. Johnson <code@dmj.io>
Maintainer David M. Johnson <code@dmj.io>
Uploaded by DavidJohnson at 2026-06-27T03:07:10Z
Category Web, Miso, Data Structures
Home page https://haskell-miso.org/
Bug tracker https://github.com/haskell-miso/miso/issues
Source repo head: git clone https://github.com/haskell-miso/miso.git
Distributions LTSHaskell:1.8.7.0, Stackage:1.11.0.0
Reverse Dependencies 9 direct, 0 indirect [details]
Downloads 36394 total (104 in the last 30 days)
Rating 2.25 (votes: 2) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2026-06-27 [all 1 reports]

Readme for miso-1.12.0.0

[back to package description]

miso

A Haskell library for building web and mobile applications

Matrix #haskell-miso:matrix.org Cachix Build Status Hackage

Inspired by Elm and React. See the GitHub org. Try it. Read the docs.

Key features

  • Virtual DOM with recursive diffing and patching algorithm
  • Attribute and property normalization, event delegation, and event batching
  • Model-View-Update paradigm
  • Pure by default
  • SVG, 2D Canvas, and WebGL (via three.js)
  • Fetch, Server-Sent Events, and WebSocket support
  • Type-safe client-side routing
  • An extensible subscription system for long-running effects and third-party library integration
  • Lifecycle hooks (onCreated, onDestroyed, mount, unmount)
  • Reactive extensions for fine-grained reactivity
  • Component, Fragment and Props features.

It makes heavy use of the GHC JavaScript FFI and maintains minimal dependencies. It can be considered a shallow embedded domain-specific language for modern web programming. Compilation targets include JavaScript and WebAssembly via GHC. Hot reload is provided through WASM browser mode integrated with ghciwatch.

[!TIP] See the Haskell miso organization on GitHub for the full ecosystem of packages and examples 🍜

Table of Contents

Playground 🛝

An interactive playground is available at try.haskell-miso.org. It allows editing and running applications directly in the browser without any local toolchain setup, and is useful for experimentation and sharing minimal reproducible examples.

Quick Start (Nix) ⚡

[!TIP] The miso-sampler template repository includes a counter application with build scripts for WebAssembly, JavaScript, and native GHC targets.

The following requires Nix Flakes. See also Binary cache to avoid rebuilding dependencies.

# Install nix 
curl -L https://nixos.org/nix/install | sh

# Enable flakes
echo 'experimental-features = nix-command flakes' >> ~/.config/nix/nix.conf

# Clone, build and serve
git clone https://github.com/haskell-miso/miso-sampler && cd miso-sampler
nix develop .#wasm --command bash -c 'make && make serve'

Manual Setup (GHCup / Cabal)

To develop applications without Nix, acquire GHC and cabal via GHCup.

[!TIP] For users new to Haskell tooling, GHCup is the recommended way to install both GHC and cabal.

A minimal application requires three files:

  • cabal.project
  • app.cabal
  • Main.hs

cabal.project

packages:
  .

source-repository-package
  type: git
  location: https://github.com/dmjio/miso
  branch: master

[!NOTE] Pinning to a specific tag: or commit: rather than branch: master is recommended for reproducible builds.

app.cabal

Using cabal-version: 2.2 or later enables common stanzas, which allow a single .cabal file to target both the WASM and JS backends.

cabal-version: 2.2
name: app
version: 0.1.0.0
synopsis: Sample miso app
category: Web

common options
  if arch(wasm32)
    ghc-options:
      -no-hs-main
      -optl-mexec-model=reactor
      "-optl-Wl,--export=hs_start"
    cpp-options:
      -DWASM

  if arch(javascript)
     ld-options:
       -sEXPORTED_RUNTIME_METHODS=HEAP8

executable app
  import:
    options
  main-is:
    Main.hs
  build-depends:
    base, miso
  default-language:
    Haskell2010

Main.hs

A counter application demonstrating the Model-View-Update pattern:

----------------------------------------------------------------------------
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE LambdaCase        #-}
{-# LANGUAGE CPP               #-}
----------------------------------------------------------------------------
module Main where
----------------------------------------------------------------------------
import           Miso
import qualified Miso.Html as H
import           Miso.Lens
----------------------------------------------------------------------------
-- | Sum type for App events
data Action
  = AddOne
  | SubtractOne
  | SayHelloWorld
  deriving (Show, Eq)
----------------------------------------------------------------------------
-- | Entry point for a miso application
main :: IO ()
main = startApp defaultEvents app
----------------------------------------------------------------------------
-- | WASM export, required when compiling w/ the WASM backend.
#ifdef WASM
foreign export javascript "hs_start" main :: IO ()
#endif
----------------------------------------------------------------------------
-- | `vcomp` takes as arguments the initial model, update function, view function
app :: App Int Action
app = vcomp 0 updateModel viewModel
----------------------------------------------------------------------------
-- | Updates model, optionally introduces side effects
updateModel :: Action -> Effect parent props Int Action
updateModel = \case
  AddOne -> this += 1
  SubtractOne -> this -= 1
  SayHelloWorld -> io_ $ do
    alert "Hello World"
    consoleLog "Hello World"
----------------------------------------------------------------------------
-- | Constructs a virtual DOM from a model
viewModel :: () -> Int -> View Int Action
viewModel _props x = vfrag
    [ H.button_ [ H.onClick AddOne ] [ text "+" ]
    , text (ms x)
    , H.button_ [ H.onClick SubtractOne ] [ text "-" ]
    , H.br_ []
    , H.button_ [ H.onClick SayHelloWorld ] [ text "Alert Hello World!" ]
    ]
----------------------------------------------------------------------------

Hot Reload 🔥

Hot reload is supported via WASM browser mode and ghciwatch. This provides incremental recompilation with automatic browser refresh on file changes. See the miso-sampler browser mode documentation for setup instructions.

Installation

See Installation for platform-specific installation instructions.

Haddocks

Official API reference. See also the Miso module for a guided entry point into the library.

Platform URL
GHCJS Link
GHC Link

Wiki

See the DeepWiki entry for an AI-assisted exploration of the source code.

Ask DeepWiki

Architecture

miso follows the Model-View-Update (MVU) pattern. A Component is parameterized by a model type and an action type. The update function maps actions to Effect values — a monad over the Reader/Writer/State stack — which can both modify the model and schedule IO operations. Long-running effects are expressed as Subscriptions that push actions into the component via a Sink.

For (client/server) applications, the recommended layout is a single .cabal file with separate executable stanzas conditioned on the compiler target. An example of this structure is the haskell-miso.org source.

[!TIP] For a worked example of a Nix-based client/server deployment, see the nix scripts for haskell-miso.org.

Examples

Examples are hosted under the haskell-miso GitHub organization. Each repository contains its own build instructions. The recommended approach is to build via nix.

[!TIP] Use cachix to avoid rebuilding shared dependencies: cachix use haskell-miso-cachix

Name Description Source Demo Author
TodoMVC TodoMVC reference implementation Source Demo @dmjio
2048 Clone of the 2048 sliding-tile game Source Demo @ptigwe
Flatris Tetris variant Source Demo @ptigwe
Plane Flappy-bird-style game Source Demo @Lermex
Snake Classic Snake game Source Demo @lbonn
SVG SVG rendering Source Demo @dmjio
Fetch HTTP API interaction via Fetch Source Demo @dmjio
File Reader FileReader API Source Demo @dmjio
Mario Physics-based platformer Source Demo @dmjio
WebSocket WebSocket communication Source Demo @dmjio
Router Client-side routing Source Demo @dmjio
Canvas 2D 2D Canvas rendering Source Demo @dmjio
MathML MathML rendering Source Demo @dmjio
Simple Counter (minimal example) Source Demo @dmjio
SSE Server-Sent Events Source Demo @dmjio
Three.js 3D rendering via Three.js Source Demo @juliendehos
Space Invaders Space Invaders clone Source Demo @juliendehos
Audio Audio playback Source Demo @juliendehos
Video Video playback Source Demo @juliendehos
WebVR WebVR via A-Frame Source Demo @dmjio
Reactivity Fine-grained reactive updates Source Demo @dmjio
Chess Chess game Source Demo @dmjio

Interacting with HTTP APIs 🔌

Two approaches are supported:

  1. For simple JSON-based APIs, use the Fetch module directly.

  2. For more complex cases, define a Servant API and derive client functions via servant-miso-client.

    The Fetch example (Demo) demonstrates the required setup. Add the following to cabal.project to use servant-miso-client:

    source-repository-package
      type: git
      location: https://github.com/haskell-miso/servant-miso-client
      tag: master
    

Testing ✅

The test suite spans three layers:

  • Unit tests — the TypeScript runtime (virtual DOM, diffing, event delegation) is tested with bun, covering the core diff engine and supporting utilities.
  • Integration tests — Haskell internals are exercised via a WASM test suite that runs the runtime in a headless browser environment, verifying component lifecycle, subscriptions, and state transitions.
  • End-to-end tests — selected applications such as TodoMVC are tested end-to-end against a live browser to validate full-stack rendering and event handling.

A full coverage report for the TypeScript layer is available at coverage.haskell-miso.org.

[!NOTE] To run the TypeScript tests, install bun first.

$ curl -fsSL https://bun.sh/install | bash

or

$ nix-env -iA bun -f '<nixpkgs>'

and

$ bun install && bun run test

Native 📱

iOS and Android applications are supported via LynxJS. See the miso-lynx repository for details.

Benchmarks 🏎️

According to benchmarks, miso performs competitively relative to other frameworks.

Nix nixos-snowflake

Nix provides a reproducible environment for building, configuring, and deploying applications. The haskell-miso.org source serves as a reference for this workflow.

Pinning nixpkgs 📌

By default, miso uses a pinned version of nixpkgs known as pkgs.

[!NOTE] miso also maintains a legacyPkgs nixpkgs pin for tools such as nixops and for builds using the original GHCJS 8.6 backend.

Binary cache

Linux and macOS users can use a binary cache to avoid rebuilding dependencies. Follow the setup instructions on cachix.

$ cachix use haskell-miso-cachix

For CI pipelines using GitHub Actions:

- name: Install cachix
  uses: cachix/cachix-action@v16
  with:
    name: haskell-miso-cachix

Community :octocat:

Maintainers

@dmjio

Commercial 🚀

Since its launch, miso has been deployed across a range of domains, including quantitative finance, network security, defense research, academia, SaaS, the public sector, and non-profit organizations. The largest known deployment consisted of approximately 200,000 LOC serving over 10,000 users.

Contributing

Contributions are welcome. Open an issue or submit a pull request.

See CONTRIBUTING for guidelines.

Contributors 🦾

[!NOTE] This project exists thanks to all the people who contribute.

Partnerships 🤝

For inquiries regarding feature sponsorship or corporate partnerships, contact support@haskell-miso.org.

Backers

Become a financial contributor to help sustain the project.

organizations

Support this project with your organization. Your logo will appear here with a link to your website.

History 📜

miso is a portmanteau of micro and isomorphic.

miso was initiated in 2016 as a research project exploring two directions:

The project addresses the JavaScript problem in Haskell by providing component abstractions and rendering primitives familiar to practitioners of frameworks such as React and Vue.js. The library has since expanded to include multiple rendering backends and native mobile support for iOS, Android, and HarmonyOS via LynxJS.

License

BSD3 © dmjio