dont-track-me-google
Firefox and Chrome extensions to prevent Google from making links ugly.
A library for building web and mobile applications
Inspired by Elm and React. See the GitHub org. Try it. Read the docs.
onCreated, onDestroyed, mount, unmount)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 🍜
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.
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'
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.projectapp.cabalMain.hscabal.projectpackages: . 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.cabalUsing 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.hsA 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 context 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 :: context -> props -> Int -> View context Action
viewModel _context _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 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.
See Installation for platform-specific installation instructions.
Official API reference. See also the Miso module for a guided entry point into the library.
| Platform | URL |
|---|---|
| GHCJS | Link |
| GHC | Link |
See the DeepWiki entry for an AI-assisted exploration of the source code.
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 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 |
Two approaches are supported:
For simple JSON-based APIs, use the Fetch module directly.
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
The test suite spans three layers:
diff engine and supporting utilities.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
iOS and Android applications are supported via LynxJS. See the miso-lynx repository for details.
According to benchmarks, miso performs competitively relative to other frameworks.
Nix provides a reproducible environment for building, configuring, and deploying applications. The haskell-miso.org source serves as a reference for this workflow.
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.
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
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.
Contributions are welcome. Open an issue or submit a pull request.
See CONTRIBUTING for guidelines.
Note
This project exists thanks to all the people who contribute.
For inquiries regarding feature sponsorship or corporate partnerships, contact support@haskell-miso.org.
Become a financial contributor to help sustain the project.
Support this project with your organization. Your logo will appear here with a link to your website.
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.
BSD3 © dmjio
more like this
Firefox and Chrome extensions to prevent Google from making links ugly.
search projects, people, and tags