diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -9,12 +9,12 @@
 
 <p align="center">
   <a href="https://haskell-miso-slack.herokuapp.com">
-	<img src="https://img.shields.io/badge/slack-miso-E01563.svg?style=flat-square" alt="Miso Slack">
+<img src="https://img.shields.io/badge/slack-miso-E01563.svg?style=flat-square" alt="Miso Slack">
   </a>
   <a href="https://haskell.org">
 	<img src="https://img.shields.io/badge/language-Haskell-orange.svg?style=flat-square" alt="Haskell">
   </a>
-  <a href="https://haskell-miso.cachix.org">
+  <a href="https://miso-haskell.cachix.org">
 	<img src="https://img.shields.io/badge/build-cachix-yellow.svg?style=flat-square" alt="Cachix">
   </a>
   <a href="https://travis-ci.org/dmjio/miso">
@@ -59,6 +59,8 @@
   - [GHC](#ghc)
   - [GHCJS](#ghcjs)
 - [Sample Application](#sample-application)
+- [Transition Application](#transition-application)
+- [Live reload with JSaddle](#live-reload-with-jsaddle)
 - [Building examples](#building-examples)
 - [Coverage](#coverage)
 - [Isomorphic](#isomorphic)
@@ -66,11 +68,13 @@
 - [Binary cache](#binary-cache)
 - [Benchmarks](#benchmarks)
 - [Maintainers](#maintainers)
+- [Commercial Users](#commercial-users)
 - [Contributing](#contributing)
+- [Contributors](#contributors)
 - [License](#license)
 
 ## Quick start
-To get started quickly building applications, we recommend using the [`nix`](https://nixos.org/nix) package manager with miso's binary cache provided by [`cachix`](https://haskell-miso.cachix.org/). It is possible to use [`stack`](https://docs.haskellstack.org/en/stable/README/) to build GHCJS projects, but support for procuring `GHCJS` has been removed [as of stack 2.0](https://github.com/commercialhaskell/stack/issues/4086). `nix` is used to procure a working version of `GHCJS`. If you're using `cabal` we assume you have [obtained `GHCJS`](https://github.com/ghcjs/ghcjs#installation) by other means. All source code depicted below for the quick start app is available [here](https://github.com/dmjio/miso/tree/master/sample-app).
+To get started quickly building applications, we recommend using the [`nix`](https://nixos.org/nix) package manager with miso's binary cache provided by [`cachix`](https://miso-haskell.cachix.org/). It is possible to use [`stack`](https://docs.haskellstack.org/en/stable/README/) to build GHCJS projects, but support for procuring `GHCJS` has been removed [as of stack 2.0](https://github.com/commercialhaskell/stack/issues/4086). `nix` is used to procure a working version of `GHCJS`. If you're using `cabal` we assume you have [obtained `GHCJS`](https://github.com/ghcjs/ghcjs#installation) by other means. All source code depicted below for the quick start app is available [here](https://github.com/dmjio/miso/tree/master/sample-app).
 
 ### Begin
 To build the sample-app with `nix`, execute the commands below:
@@ -79,7 +83,7 @@
 # optional use of cache
 nix-env -iA cachix -f https://cachix.org/api/v1/install
 # optional use of cache
-cachix use haskell-miso
+cachix use miso-haskell
 git clone https://github.com/dmjio/miso
 cd miso/sample-app
 nix-build
@@ -125,11 +129,10 @@
 
 ```nix
 with (import (builtins.fetchTarball {
-  url = "https://github.com/dmjio/miso/archive/39b9e26ff41d6aab3b9d13a9d102ac56017f6a1f.tar.gz";
-  sha256 = "1lwr35p9074b7wgz0jh4f2pjc7ls8isgzmn9xl86vb6cvsm035kf";
+  url = "https://github.com/dmjio/miso/archive/425de4eb87e876428df4872a595ac1a0717dd165.tar.gz";
+  sha256 = "1mc44vnx8qmvxkrvxhzlnrza8shnk8a0ad7hfk8hlblzrd9ha5id";
 }) {});
-with pkgs.haskell.packages;
-ghcjs.callCabal2nix "app" ./. {}
+pkgs.haskell.packages.ghcjs.callCabal2nix "app" ./. {}
 ```
 
 Add the source from [Sample Application](#sample-application) to `app/Main.hs`
@@ -166,7 +169,7 @@
 
 For incremental development inside of the `nix-shell` we recommend using a tool like [`entr`](http://eradman.com/entrproject/) to automatically rebuild on file changes, or roll your own solution with `inotify`.
 ```
-ag -l | entr 'cabal build'
+ag -l | entr cabal build
 ```
 
 ### Architecture
@@ -268,11 +271,16 @@
 
 -- | Updates model, optionally introduces side effects
 updateModel :: Action -> Model -> Effect Action Model
-updateModel AddOne m = noEff (m + 1)
-updateModel SubtractOne m = noEff (m - 1)
-updateModel NoOp m = noEff m
-updateModel SayHelloWorld m = m <# do
-  putStrLn "Hello World" >> pure NoOp
+updateModel action m =
+  case action of
+    AddOne
+      -> noEff (m + 1)
+    SubtractOne
+      -> noEff (m - 1)
+    NoOp
+      -> noEff m
+    SayHelloWorld
+      -> m <# do consoleLog "Hello World" >> pure NoOp
 
 -- | Constructs a virtual DOM from a model
 viewModel :: Model -> View Action
@@ -283,6 +291,83 @@
  ]
 ```
 
+## Transition application
+
+An alternative, more powerful interface for constructing `miso` applications is using the `Transition` interface.
+`Transition` is based on the `StateT` monad transformer, and can be used to construct components. It also works
+very nicely with lenses based on `MonadState` (i.e. `(.=)`, `(%=)`,`(+=)`,`(-=)`).
+
+
+```haskell
+-- | Haskell language pragma
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards   #-}
+
+-- | Haskell module declaration
+module Main where
+
+-- | Miso framework import
+import Miso
+import Miso.String
+
+-- | Lens import
+import Control.Lens
+
+-- | Type synonym for an application model
+data Model
+  = Model
+  { _counter :: Int
+  } deriving (Show, Eq)
+
+counter :: Lens' Model Int
+counter = lens _counter $ \record field -> record { _counter = field }
+
+-- | Sum type for application events
+data Action
+  = AddOne
+  | SubtractOne
+  | NoOp
+  | SayHelloWorld
+  deriving (Show, Eq)
+
+-- | Entry point for a miso application
+main :: IO ()
+main = startApp App {..}
+  where
+    initialAction = SayHelloWorld -- initial action to be executed on application load
+    model  = 0                    -- initial model
+    update = fromTransition . updateModel -- update function
+    view   = viewModel            -- view function
+    events = defaultEvents        -- default delegated events
+    subs   = []                   -- empty subscription list
+    mountPoint = Nothing          -- mount point for application (Nothing defaults to 'body')
+
+-- | Updates model, optionally introduces side effects
+updateModel :: Action -> Transition Action Model ()
+updateModel action =
+  case action of
+    AddOne
+      -> counter += 1
+    SubtractOne
+      -> counter -= 1
+    NoOp
+      -> pure ()
+    SayHelloWorld
+      -> scheduleIO_ (consoleLog "Hello World")
+
+-- | Constructs a virtual DOM from a model
+viewModel :: Model -> View Action
+viewModel x = div_ [] [
+   button_ [ onClick AddOne ] [ text "+" ]
+ , text (ms x)
+ , button_ [ onClick SubtractOne ] [ text "-" ]
+ ]
+```
+
+## Live reload with JSaddle
+
+It is possible to build `miso` applications with `ghcid`, `jsaddle` that allow live reloading of your application in reponse to changes in application code. See the [README](https://github.com/dmjio/miso/blob/master/sample-app-jsaddle/README.md) in the `sample-app-jsaddle` folder for more information.
+
 ## Building examples
 
 The easiest way to build the examples is with the [`nix`](https://nixos.org/nix/) package manager
@@ -346,27 +431,61 @@
 
 ## Binary cache
 
-`nix` users on a Linux or OSX distro can take advantage of a [binary cache](https://haskell-miso.cachix.org) for faster builds. To use the binary cache follow the instructions on [cachix](https://haskell-miso.cachix.org/).
+`nix` users on a Linux or OSX distro can take advantage of a [binary cache](https://miso-haskell.cachix.org) for faster builds. To use the binary cache follow the instructions on [cachix](https://miso-haskell.cachix.org/).
 
 ```bash
-cachix use haskell-miso
+cachix use miso-haskell
 ```
 
 ## Benchmarks
 
 [According to benchmarks](https://rawgit.com/krausest/js-framework-benchmark/master/webdriver-ts-results/table.html), `miso` is among the fastest functional programming web frameworks, second only to [Elm](http://elm-lang.org).
 
-<img src="https://cdn-images-1.medium.com/max/1600/1*6EjJTf1mhlTxd4QWsygCwA.png" width="500" height="600" />
+<a target="_blank" href="https://rawgit.com/krausest/js-framework-benchmark/master/webdriver-ts-results/table.html"><img src="https://cdn-images-1.medium.com/max/1600/1*6EjJTf1mhlTxd4QWsygCwA.png" width="500" height="600" /></a>
 
 ## Maintainers
 
 [@dmjio](https://github.com/dmjio)
 
+## Commercial Users
+  - [Polimorphic](https://www.polimorphic.com)
+  - [LumiGuide](https://lumi.guide/en/)
+
 ## Contributing
 
 Feel free to dive in! [Open an issue](https://github.com/dmjio/miso/issues/new) or submit [PRs](https://github.com/dmjio/miso/pulls).
 
 See [CONTRIBUTING](https://github.com/dmjio/miso/blob/master/CONTRIBUTING.md) for more info.
+
+## Contributors
+
+### Code Contributors
+
+This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
+<a href="https://github.com/dmjio/miso/graphs/contributors"><img src="https://opencollective.com/miso/contributors.svg?width=890&button=false" /></a>
+
+### Financial Contributors
+
+Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/miso/contribute)]
+
+#### Individuals
+
+<a href="https://opencollective.com/miso"><img src="https://opencollective.com/miso/individuals.svg?width=890"></a>
+
+#### Organizations
+
+Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/miso/contribute)]
+
+<a href="https://opencollective.com/miso/organization/0/website"><img src="https://opencollective.com/miso/organization/0/avatar.svg"></a>
+<a href="https://opencollective.com/miso/organization/1/website"><img src="https://opencollective.com/miso/organization/1/avatar.svg"></a>
+<a href="https://opencollective.com/miso/organization/2/website"><img src="https://opencollective.com/miso/organization/2/avatar.svg"></a>
+<a href="https://opencollective.com/miso/organization/3/website"><img src="https://opencollective.com/miso/organization/3/avatar.svg"></a>
+<a href="https://opencollective.com/miso/organization/4/website"><img src="https://opencollective.com/miso/organization/4/avatar.svg"></a>
+<a href="https://opencollective.com/miso/organization/5/website"><img src="https://opencollective.com/miso/organization/5/avatar.svg"></a>
+<a href="https://opencollective.com/miso/organization/6/website"><img src="https://opencollective.com/miso/organization/6/avatar.svg"></a>
+<a href="https://opencollective.com/miso/organization/7/website"><img src="https://opencollective.com/miso/organization/7/avatar.svg"></a>
+<a href="https://opencollective.com/miso/organization/8/website"><img src="https://opencollective.com/miso/organization/8/avatar.svg"></a>
+<a href="https://opencollective.com/miso/organization/9/website"><img src="https://opencollective.com/miso/organization/9/avatar.svg"></a>
 
 ## License
 
diff --git a/frontend-src/Miso/Html/Internal.hs b/frontend-src/Miso/Html/Internal.hs
--- a/frontend-src/Miso/Html/Internal.hs
+++ b/frontend-src/Miso/Html/Internal.hs
@@ -49,6 +49,7 @@
   -- * Life cycle events
   , onCreated
   , onDestroyed
+  , onBeforeDestroyed
   -- * Events
   , defaultEvents
   -- * Subscription type
@@ -279,6 +280,19 @@
   Attribute $ \sink n -> do
     cb <- callbackToJSVal =<< asyncCallback (liftIO (sink action))
     set "onDestroyed" cb n
+    registerCallback cb
+
+-- | @onBeforeDestroyed action@ is an event that gets called before the DOM element
+-- is removed from the DOM. The @action@ is given the DOM element that was
+-- removed from the DOM tree.
+--
+-- Important note: Any node that uses this event MUST have a unique @Key@,
+-- otherwise the event may not be reliably called!
+onBeforeDestroyed :: action -> Attribute action
+onBeforeDestroyed action =
+  Attribute $ \sink n -> do
+    cb <- callbackToJSVal =<< asyncCallback (liftIO (sink action))
+    set "onBeforeDestroyed" cb n
     registerCallback cb
 
 -- | @style_ attrs@ is an attribute that will set the @style@
diff --git a/ghc-src/Miso/Html/Internal.hs b/ghc-src/Miso/Html/Internal.hs
--- a/ghc-src/Miso/Html/Internal.hs
+++ b/ghc-src/Miso/Html/Internal.hs
@@ -44,6 +44,7 @@
   -- * Life cycle events
   , onCreated
   , onDestroyed
+  , onBeforeDestroyed
   ) where
 
 import           Data.Aeson (Value(..), ToJSON(..))
@@ -241,6 +242,12 @@
 -- removed from the DOM tree.
 onDestroyed :: action -> Attribute action
 onDestroyed _ = E ()
+
+-- | @onBeforeDestroyed action@ is an event that gets called before the DOM element
+-- is removed from the DOM. The @action@ is given the DOM element that was
+-- removed from the DOM tree.
+onBeforeDestroyed :: action -> Attribute action
+onBeforeDestroyed _ = E ()
 
 -- | Constructs CSS for a DOM Element
 --
diff --git a/ghcjs-ffi/Miso/FFI.hs b/ghcjs-ffi/Miso/FFI.hs
--- a/ghcjs-ffi/Miso/FFI.hs
+++ b/ghcjs-ffi/Miso/FFI.hs
@@ -32,6 +32,7 @@
 
    , now
    , consoleLog
+   , consoleLogJSVal
    , stringify
    , parse
    , clearBody
@@ -61,7 +62,7 @@
    ) where
 
 import           Control.Concurrent
-import           Data.Aeson hiding (Object)
+import           Data.Aeson                 hiding (Object)
 import           Data.JSString
 import           Data.JSString.Int
 import           Data.JSString.RealFloat
@@ -132,7 +133,10 @@
 
 -- | Console-logging
 foreign import javascript unsafe "console.log($1);"
-  consoleLog :: JSVal -> IO ()
+  consoleLog :: JSString -> IO ()
+
+foreign import javascript unsafe "console.log($1);"
+  consoleLogJSVal :: JSVal -> IO ()
 
 -- | Converts a JS object into a JSON string
 foreign import javascript unsafe "$r = JSON.stringify($1);"
diff --git a/jsaddle-ffi/Miso/FFI.hs b/jsaddle-ffi/Miso/FFI.hs
--- a/jsaddle-ffi/Miso/FFI.hs
+++ b/jsaddle-ffi/Miso/FFI.hs
@@ -30,6 +30,7 @@
 
    , now
    , consoleLog
+   , consoleLogJSVal
    , stringify
    , parse
    , clearBody
@@ -127,8 +128,14 @@
 now = fromJSValUnchecked =<< (jsg "performance" # "now" $ ())
 
 -- | Console-logging
-consoleLog :: JSVal -> JSM ()
+consoleLog :: JSString -> JSM ()
 consoleLog v = do
+  _ <- jsg "console" # "log" $ [toJSString v]
+  pure ()
+
+-- | Console-logging
+consoleLogJSVal :: JSVal -> JSM ()
+consoleLogJSVal v = do
   _ <- jsg "console" # "log" $ [v]
   pure ()
 
diff --git a/jsbits/diff.js b/jsbits/diff.js
--- a/jsbits/diff.js
+++ b/jsbits/diff.js
@@ -16,6 +16,7 @@
 };
 
 window['destroyNode'] = function destroyNode(obj, parent) {
+  window['callBeforeDestroyedRecursive'](obj);
   parent.removeChild(obj['domRef']);
   window['callDestroyedRecursive'](obj);
 };
@@ -30,6 +31,16 @@
   if (obj['onDestroyed']) obj['onDestroyed']();
 };
 
+window['callBeforeDestroyed'] = function callBeforeDestroyed(obj) {
+  if (obj['onBeforeDestroyed']) obj['onBeforeDestroyed']();
+};
+
+window['callBeforeDestroyedRecursive'] = function callBeforeDestroyedRecursive(obj) {
+  window['callBeforeDestroyed'](obj);
+  for (var i in obj.children)
+    window['callBeforeDestroyedRecursive'](obj.children[i]);
+};
+
 window['diffTextNodes'] = function diffTextNodes(c, n) {
   if (c['text'] !== n['text']) c['domRef'].textContent = n['text'];
   n['domRef'] = c['domRef'];
@@ -37,6 +48,7 @@
 
 window['replaceElementWithText'] = function replaceElementWithText(c, n, parent, doc) {
   n['domRef'] = doc.createTextNode(n['text']);
+  window['callBeforeDestroyedRecursive'](c);
   parent.replaceChild(n['domRef'], c['domRef']);
   window['callDestroyedRecursive'](c);
 };
@@ -68,6 +80,7 @@
     window['populate'](c, n, doc);
   } else {
     window['createElement'](n, doc);
+    window['callBeforeDestroyedRecursive'](c);
     parent.replaceChild(n['domRef'], c['domRef']);
     window['callDestroyedRecursive'](c);
     window['callCreated'](n);
diff --git a/jsbits/isomorphic.js b/jsbits/isomorphic.js
--- a/jsbits/isomorphic.js
+++ b/jsbits/isomorphic.js
@@ -1,5 +1,5 @@
 window = typeof window === 'undefined' ? {} : window;
-window['copyDOMIntoVTree'] = function copyDOMIntoVTree(mountPoint, vtree, doc) {
+window['copyDOMIntoVTree'] = function copyDOMIntoVTree(mountPoint, vtree, doc = window.document) {
   var node = mountPoint ? mountPoint.firstChild : doc.body.firstChild;
   if (!window['walk'](vtree, node, doc)) {
     console.warn('Could not copy DOM into virtual DOM, falling back to diff');
diff --git a/miso.cabal b/miso.cabal
--- a/miso.cabal
+++ b/miso.cabal
@@ -1,5 +1,5 @@
 name:                miso
-version:             1.2.0.0
+version:             1.3.0.0
 category:            Web, Miso, Data Structures
 license:             BSD3
 license-file:        LICENSE
diff --git a/tests/Main.hs b/tests/Main.hs
--- a/tests/Main.hs
+++ b/tests/Main.hs
@@ -102,7 +102,7 @@
 runTests :: TestM () -> IO ()
 runTests t = do
   results <- toJSVal =<< toResult <$> execStateT t []
-  consoleLog results
+  consoleLogJSVal results
   writeToGlobalObject results
     where
       toResult :: [Test] -> TestResult
