dmjio
miso
Haskell

:ramen: A tasty web framework

Last updated Jul 9, 2026
2.4k
Stars
165
Forks
13
Issues
0
Stars/day
Attention Score
85
Language breakdown
Haskell 76.2%
TypeScript 19.8%
JavaScript 2.4%
Nix 1.3%
Makefile 0.1%
Shell 0.0%
โ–ธ Files click to expand
README

miso

A 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 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

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: -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.

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

ยฉ 2026 GitRepoTrend ยท dmjio/miso ยท Updated daily from GitHub