miso: a Haskell framework for web and mobile apps that compiles to JavaScript and WebAssembly
:ramen: A tasty Haskell web and mobile framework
At a glance
- What is it?
- miso is a Model-View-Update framework for building browser and mobile interfaces in Haskell, with a virtual DOM, a JavaScript FFI and a Nix-based toolchain. It is a good fit if your team already writes Haskell; the setup cost is real if it does not.
- Who is it for?
- miso is worth adopting when your team already writes Haskell and you want the same Model-View-Update structure on the web, on mobile through miso-lynx, and in native GHC builds. It is the wrong tool if nobody on the team reads Haskell, or if you need a framework with a large supply of third-party components.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Haskell, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What miso solves, and who it is aimed at
Writing browser interfaces in Haskell has always meant picking between an opaque binding layer and hand-written JavaScript glue. miso takes the other route: it treats the DOM as a value your program produces, and keeps the update logic in Haskell. The README describes it as a library for building web and mobile applications, inspired by Elm and React, and calls it a shallow embedded domain-specific language for modern web programming.
The audience is narrow and specific. You need a working Haskell toolchain, and you need to be comfortable reading type errors. In exchange you get one language across the view layer, the state transitions and the data types that flow between them. Teams that already run Haskell services can share types between the client and the server instead of maintaining a schema in two places. Teams that do not write Haskell will spend their first week on GHCup, cabal and the compiler rather than on the framework, and that cost is not something miso hides.
The mobile side is not part of the core package. The README points at a separate repository, miso-lynx, for mobile applications, so treat mobile as an adjacent project rather than a feature you get when you install miso.
The Model-View-Update loop and the virtual DOM underneath
miso follows the Elm architecture. Your application holds a model, a view function turns that model into a tree of virtual nodes, and an update function takes a message plus the current model and returns a new model. The README lists this as the Model-View-Update paradigm, and the counter example in the manual setup section is exactly that shape.
Rendering is handled by a virtual DOM with what the README calls a recursive diffing and patching algorithm. The framework also does attribute and property normalization, event delegation and event batching, which means DOM listeners are not attached one per element and multiple messages arriving in the same tick can be processed together. For long-running work there is a subscription system, described as extensible, intended for effects and for integrating third-party libraries.
What is unusual is the compilation story. miso makes heavy use of the GHC JavaScript FFI and keeps dependencies minimal. Compilation targets include JavaScript and WebAssembly through GHC, and hot reload comes from WASM browser mode integrated with ghciwatch. That combination is the reason the framework exists at all: the same source can be built for the browser as JavaScript or as a WASM module, and the repository also ships a native sample application, so the rendering logic can be exercised outside a browser.
Installing miso with Nix flakes and running the sampler
The README offers two paths. The quick start uses Nix flakes and the miso-sampler template repository, which contains a counter application with build scripts for WebAssembly, JavaScript and native GHC targets. The commands below are copied from that section; they install Nix, enable flakes, then clone, build and serve the sample.
# 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'After that runs, the sampler is served locally and the counter responds to clicks. The README also points at a binary cache, haskell-miso-cachix.cachix.org, which avoids rebuilding dependencies from source; without it the first build pulls and compiles a large amount of Haskell.
If you would rather not use Nix, the manual setup needs GHC and cabal from GHCup, and three files: cabal.project, app.cabal and Main.hs. The cabal.project pulls miso straight from git.
packages:
.
source-repository-package
type: git
location: https://github.com/dmjio/miso
branch: masterThe README notes that pinning to a specific tag: or commit: instead of branch: master is recommended for reproducible builds, and that is worth taking literally. The app.cabal uses cabal-version: 2.2 or later so that common stanzas can target both backends. Under arch(wasm32) it passes -no-hs-main, -optl-mexec-model=reactor and "-optl-Wl,--export=hs_start" along with the -DWASM cpp option, and under arch(javascript) it passes -sEXPORTED_RUNTIME_METHODS=HEAP8. The executable then depends on base and miso. Main.hs holds the counter that demonstrates the loop.
Where miso is the wrong choice
The first limitation is the toolchain. Everything in the README assumes GHC and either Nix or cabal. There is no npm install path that gives you a working project, even though the package is published to npm as haskell-miso with a version badge in the README. That npm entry is the JavaScript runtime side of the framework, not a way to skip the Haskell compiler.
Build times are the second issue. The README's own advice to use a binary cache exists because compiling the dependency set from source is slow enough to matter. On a machine without the cache, a first build is a project in itself.
The third limitation is the ecosystem. React and its competitors come with a large catalogue of ready-made components. miso gives you primitives: virtual DOM, events, subscriptions, routing, and bindings for SVG, 2D Canvas and WebGL through three.js. Anything beyond that you write, or you wrap a JavaScript library through the FFI. For a dashboard assembled from off-the-shelf widgets, that is a poor trade.
Finally, the README does not document a rollback or downgrade path for a bad release, and it does not describe a migration guide between versions. The CHANGELOG.md file is in the repository, so that is where you would look, but the README itself is silent on upgrading.
How miso differs from Elm and from React
Elm is the closest comparison and the README names it as an inspiration. Both use a model, a view and an update function, and both give you a virtual DOM. The difference is the host language. Elm is its own language with its own compiler and its own package registry, so adopting it means adopting a second language next to whatever your backend uses. miso is a library inside Haskell, published on Hackage and pinned through cabal, so the same language and the same build tool can cover client and server. The cost is that Elm's compiler is famously helpful with error messages, while miso inherits GHC's.
React is the other reference point, and the README borrows several concepts from it by name: Component, Context, Fragment and Props. The approaches still diverge. React applications are written in JavaScript or TypeScript and rendered by a runtime you ship; miso applications are compiled ahead of time, and the README lists JavaScript and WebAssembly as compilation targets through GHC. That means no interpreter in the bundle, but it also means every change goes through a compiler. If you want the React component ecosystem, React is the answer; if you want the component model without leaving Haskell, miso is the closer fit.
Maintenance, licensing and upgrade cost
The repository is not archived, and the last push was on 2026-09-27, one day before this was written. Releases have been frequent: 1.12.0 on 2026-06-27, 1.13.0 on 2026-08-30 and 1.14.0 on 2026-09-13. A cadence of roughly one minor release a month means you should expect to move your pin forward periodically rather than sit on a version for a year, and the README's recommendation to pin to a tag or commit gives you control over when that happens.
miso is licensed under BSD-3-Clause, the same permissive family as much of the Haskell ecosystem. That allows commercial use and modification, and it does not require you to publish your own source. The README has a Commercial section and a Partnerships section, so there are commercial arrangements around the project, but the licence on the code itself is the permissive one. This is a description of what the repository states, not legal advice; if the licence terms matter to your organisation, read the LICENSE file and talk to your own counsel.
The upgrade cost is dominated by the compiler, not the library. Because miso targets GHC's JavaScript and WebAssembly backends, a GHC upgrade can change your build before a miso upgrade does. Budget for testing both the WASM and JavaScript outputs whenever either moves.
Editorial conclusion
miso is worth adopting when your team already writes Haskell and you want the same Model-View-Update structure on the web, on mobile through miso-lynx, and in native GHC builds. It is the wrong tool if nobody on the team reads Haskell, or if you need a framework with a large supply of third-party components. Before committing, clone miso-sampler and check that the WebAssembly build and the JavaScript build both produce output in your environment, then pin the source-repository-package in cabal.project to a tag or commit instead of branch: master.
Frequently asked questions
Do I need to know Haskell to use miso?
Yes. miso is a Haskell library, and the manual setup requires GHC and cabal plus Haskell source files such as Main.hs. The README recommends GHCup for installing both tools.
Can miso build a mobile application?
The README describes miso as a library for building web and mobile applications and links to a separate repository, miso-lynx, for the mobile side. Mobile support therefore lives in that adjacent project rather than in the core package.
Does miso compile to WebAssembly or to JavaScript?
Both. The README lists JavaScript and WebAssembly as compilation targets through GHC, and the sample app.cabal uses common stanzas to pass different flags for arch(wasm32) and arch(javascript).
Can I install miso from npm instead of using Nix or cabal?
The package is published to npm as haskell-miso, but the README's setup instructions go through Nix flakes or GHCup and cabal. The npm entry is the JavaScript side of the framework, not a replacement for the Haskell toolchain.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/dmjio-miso)