:ramen: A tasty web framework
miso
A library for building web and mobile applications
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.
[!TIP]
See the miso organization on GitHub for the full ecosystem of packages and examples ๐
Table of Contents
- cabal.project - app.cabal - Main.hs - Pinning nixpkgs - Binary cache- Community
- Maintainers
- Commercial
- Contributing
- Contributors
- Partnerships
- Backers
- Organizations
- History
- License
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 specifictag:orcommit:rather thanbranch: masteris 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: -sEXPORTEDRUNTIMEMETHODS=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.
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
diffengine 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.
[!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 
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]
misoalso maintains alegacyPkgsnixpkgs pin for tools such asnixopsand for builds using the originalGHCJS 8.6backend.
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
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:
- Expressing the Elm architecture in GHCJS as an embedded domain-specific language
- Implementing reconciliation and isomorphic rendering techniques from the JavaScript ecosystem (Reconciliation, isomorphic JavaScript) within a purely functional setting
License
BSD3 ยฉ dmjio