diff --git a/.ghci b/.ghci
new file mode 100644
--- /dev/null
+++ b/.ghci
@@ -0,0 +1,3 @@
+:set -fno-break-on-exception
+:def! reload (const $ return "::reload\nLanguage.Javascript.JSaddle.Warp.debug 3708 HelloMain.helloMain")
+
diff --git a/cabal.project b/cabal.project
new file mode 100644
--- /dev/null
+++ b/cabal.project
@@ -0,0 +1,39 @@
+flags: -overloaded-methods -overloaded-signals -overloaded-properties
+
+packages:
+ ./
+
+package gi-atk
+ flags: -overloaded-methods -overloaded-signals -overloaded-properties
+package gi-cairo
+ flags: -overloaded-methods -overloaded-signals -overloaded-properties
+package gi-gdk
+ flags: -overloaded-methods -overloaded-signals -overloaded-properties
+package gi-gdkpixbuf
+ flags: -overloaded-methods -overloaded-signals -overloaded-properties
+package gi-gio
+ flags: -overloaded-methods -overloaded-signals -overloaded-properties
+package gi-glib
+ flags: -overloaded-methods -overloaded-signals -overloaded-properties
+package gi-gobject
+ flags: -overloaded-methods -overloaded-signals -overloaded-properties
+package gi-gtk
+ flags: -overloaded-methods -overloaded-signals -overloaded-properties
+package gi-gtk-hs
+ flags: -overloaded-methods -overloaded-signals -overloaded-properties
+package gi-gtkosxapplication
+ flags: -overloaded-methods -overloaded-signals -overloaded-properties
+package gi-gtksource
+ flags: -overloaded-methods -overloaded-signals -overloaded-properties
+package gi-javascriptcore
+ flags: -overloaded-methods -overloaded-signals -overloaded-properties
+package gi-pango
+ flags: -overloaded-methods -overloaded-signals -overloaded-properties
+package gi-pangocairo
+ flags: -overloaded-methods -overloaded-signals -overloaded-properties
+package gi-soup
+ flags: -overloaded-methods -overloaded-signals -overloaded-properties
+package gi-webkit
+ flags: -overloaded-methods -overloaded-signals -overloaded-properties
+package gi-webkit2
+ flags: -overloaded-methods -overloaded-signals -overloaded-properties
diff --git a/ghcjs-dom-hello.cabal b/ghcjs-dom-hello.cabal
--- a/ghcjs-dom-hello.cabal
+++ b/ghcjs-dom-hello.cabal
@@ -1,5 +1,5 @@
 name: ghcjs-dom-hello
-version: 5.0.0.0
+version: 6.0.0.0
 cabal-version: 1.24
 build-type: Simple
 license: MIT
@@ -16,6 +16,7 @@
     Please submit any suggestions and improvements.
 category: Web
 author: Hamish Mackenzie
+data-files: .ghci cabal.project
 
 source-repository head
     type: git
@@ -38,8 +39,12 @@
         HelloMain
     build-depends:
         base >=4.2 && <5,
-        ghcjs-dom >=0.8 && <0.9,
+        ghcjs-dom >=0.9 && <0.10,
         mtl >=2.1 && <2.3
+    if !impl(ghcjs)
+        build-depends:
+            jsaddle >=0.9.2 && <0.10,
+            jsaddle-warp >=0.9.2 && <0.10
     hs-source-dirs: src
     default-language: Haskell2010
     ghc-options: -Wall -ferror-spans
@@ -48,9 +53,9 @@
     main-is: Main.hs
     build-depends:
         base,
-        ghcjs-dom,
+        ghcjs-dom-hello,
         mtl
-    hs-source-dirs: src
+    hs-source-dirs: src-bin
     default-language: Haskell2010
     ghc-options: -threaded -Wall -ferror-spans
 
@@ -58,14 +63,14 @@
     if !impl(ghcjs)
       if os(osx) || os(ios)
         build-depends:
-          jsaddle-wkwebview >=0.8 && <0.9
+          jsaddle-wkwebview >=0.9 && <0.10
       else
         if flag(webkit2gtk)
           build-depends:
-            jsaddle-webkit2gtk >=0.8 && <0.9
+            jsaddle-webkit2gtk >=0.9 && <0.10
         else
           build-depends:
-            jsaddle-webkitgtk >=0.8 && <0.9
+            jsaddle-webkitgtk >=0.9 && <0.10
 
 executable ghcjs-dom-hello-warp
     if !flag(warp) || impl(ghcjs) || os(ios)
@@ -73,10 +78,12 @@
     main-is: Warp.hs
     build-depends:
         base,
-        ghcjs-dom,
-        jsaddle-warp >=0.8 && <0.9,
+        ghcjs-dom >=0.9 && <0.10,
+        mtl >=2.1 && <2.3,
+        ghcjs-dom-hello,
+        jsaddle-warp >=0.9 && <0.10,
         mtl
-    hs-source-dirs: src
+    hs-source-dirs: src-bin
     default-language: Haskell2010
     ghc-options: -threaded -Wall -ferror-spans
 
@@ -86,15 +93,15 @@
     main-is: WebKitGTK.hs
     build-depends:
         base,
-        ghcjs-dom,
+        ghcjs-dom-hello,
         mtl
     if flag(webkit2gtk)
       build-depends:
-        jsaddle-webkit2gtk >=0.8 && <0.9
+        jsaddle-webkit2gtk >=0.9 && <0.10
     else
       build-depends:
-        jsaddle-webkitgtk >=0.8 && <0.9
-    hs-source-dirs: src
+        jsaddle-webkitgtk >=0.9 && <0.10
+    hs-source-dirs: src-bin
     default-language: Haskell2010
     ghc-options: -threaded -Wall -ferror-spans
 
@@ -104,10 +111,10 @@
     main-is: WKWebView.hs
     build-depends:
         base,
-        ghcjs-dom,
-        jsaddle-wkwebview >=0.8 && <0.9,
+        ghcjs-dom-hello,
+        jsaddle-wkwebview >=0.9 && <0.10,
         mtl
-    hs-source-dirs: src
+    hs-source-dirs: src-bin
     default-language: Haskell2010
     ghc-options: -threaded -Wall -ferror-spans
 
diff --git a/src-bin/Main.hs b/src-bin/Main.hs
new file mode 100644
--- /dev/null
+++ b/src-bin/Main.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE CPP #-}
+module Main (
+    main
+) where
+
+import HelloMain (helloMain)
+#if defined(ghcjs_HOST_OS)
+run :: a -> a
+run = id
+#elif defined(MIN_VERSION_jsaddle_wkwebview)
+import Language.Javascript.JSaddle.WKWebView (run)
+#else
+import Language.Javascript.JSaddle.WebKitGTK (run)
+#endif
+
+main :: IO ()
+main = run helloMain
+
diff --git a/src-bin/WKWebView.hs b/src-bin/WKWebView.hs
new file mode 100644
--- /dev/null
+++ b/src-bin/WKWebView.hs
@@ -0,0 +1,9 @@
+module Main (
+    main
+) where
+
+import Language.Javascript.JSaddle.WKWebView (run)
+import HelloMain (helloMain)
+
+main :: IO ()
+main = run helloMain
diff --git a/src-bin/Warp.hs b/src-bin/Warp.hs
new file mode 100644
--- /dev/null
+++ b/src-bin/Warp.hs
@@ -0,0 +1,13 @@
+module Main (
+    main
+) where
+
+import System.IO (stdout, hFlush)
+import Language.Javascript.JSaddle.Warp (run)
+import HelloMain (helloMain)
+
+main :: IO ()
+main = do
+  putStrLn "<a href=\"http://localhost:3708/\">http://localhost:3708/</a>"
+  hFlush stdout
+  run 3708 helloMain
diff --git a/src-bin/WebKitGTK.hs b/src-bin/WebKitGTK.hs
new file mode 100644
--- /dev/null
+++ b/src-bin/WebKitGTK.hs
@@ -0,0 +1,9 @@
+module Main (
+    main
+) where
+
+import Language.Javascript.JSaddle.WebKitGTK (run)
+import HelloMain (helloMain)
+
+main :: IO ()
+main = run helloMain
diff --git a/src/HelloMain.hs b/src/HelloMain.hs
--- a/src/HelloMain.hs
+++ b/src/HelloMain.hs
@@ -5,41 +5,68 @@
 import Control.Monad.IO.Class (MonadIO(..))
 import Control.Concurrent.MVar (takeMVar, putMVar, newEmptyMVar)
 
-import GHCJS.DOM (syncPoint, currentDocument)
+import GHCJS.DOM
 import GHCJS.DOM.Types
-       (Element(..), HTMLParagraphElement(..), HTMLSpanElement(..), uncheckedCastTo, JSM)
-import GHCJS.DOM.Document (getBodyUnsafe, createElement, createTextNode)
-import GHCJS.DOM.Element (setInnerHTML)
-import GHCJS.DOM.Node (appendChild)
-import GHCJS.DOM.EventM (on, mouseClientXY)
-import GHCJS.DOM.GlobalEventHandlers (click)
+import GHCJS.DOM.Document
+import GHCJS.DOM.Element
+import GHCJS.DOM.Node
+import GHCJS.DOM.EventM
+import GHCJS.DOM.GlobalEventHandlers
+import GHCJS.DOM.HTMLHyperlinkElementUtils
 
+-- | This is the main function of this application it is shared by all the different executable
+-- types included in this package.  Its type JSM () is like IO () but for anything that needs
+-- a JavaScript context to run.
+--
+-- One way to work on this application is to use ghci and jsaddle-warp.  Start ghci with
+-- your favourite tool, for instance from the command line you can run:
+-- > cabal new-repl
+--
+-- Make sure break-on-exception is off (otherwise it will break when we restart the warp server)
+-- > :set -fno-break-on-exception
+--
+-- There is a `.ghci` file in the ghcjs-dom-hello directory that redefines the :reload command so
+-- that each time :reload is used it will also run:
+-- > Language.Javascript.JSaddle.Warp.debug 3708 HelloMain.helloMain
+-- This will start a warp server on port 3708. If it was already running it will stop the
+-- old one first, but before it does it will send a signal to each of the connected browsers to
+-- refresh.  That way after the :reload they should all be refreshed automaticaly.
+-- (It also waits up to 10 seconds for the browsers to reconnect. If one is closed or in the
+-- or in the background you may have to wait for the ghci prompt to return).
+--
+-- Use `runOnAll` to run JavaScript on all the connected browsers.  For instance the following
+-- will print the HTML from the body of each connected browser:
+-- > Language.Javascript.JSaddle.Debug.runOnAll_ $ currentDocumentUnchecked >>= getBodyUnchecked >>= getInnerHTML >>= liftIO . putStrLn
 helloMain :: JSM ()
 helloMain = do
-    Just doc <- currentDocument
-    body <- getBodyUnsafe doc
-    setInnerHTML body (Just "<h1>Kia ora (Hi)</h1>")
+    doc <- currentDocumentUnchecked
+    body <- getBodyUnchecked doc
+    setInnerHTML body "<h1>Kia ora (Hi)</h1>"
+
+    -- Add a mouse click event handler to the document
     _ <- on doc click $ do
         (x, y) <- mouseClientXY
         newParagraph <- uncheckedCastTo HTMLParagraphElement <$> createElement doc "p"
         text <- createTextNode doc $ "Click " ++ show (x, y)
-        _ <- appendChild newParagraph text
-        _ <- appendChild body newParagraph
-        return ()
+        appendChild_ newParagraph text
+        appendChild_ body newParagraph
 
-    -- Make an exit button
+    -- Make an exit link
     exitMVar <- liftIO newEmptyMVar
-    exit <- uncheckedCastTo HTMLSpanElement <$> createElement doc "span"
+    exit <- uncheckedCastTo HTMLAnchorElement <$> createElement doc "a"
     text <- createTextNode doc "Click here to exit"
-    _ <- appendChild exit text
-    _ <- appendChild body exit
-    _ <- on exit click $ liftIO $ putMVar exitMVar ()
+    appendChild_ exit text
+    appendChild_ body exit
 
-    -- Force all all the lazy evaluation to be executed
+    -- Set an href for the link, but use preventDefault to stop it working
+    -- (demonstraights synchronous callbacks into haskell, as preventDefault
+    -- must be called inside the JavaScript event handler function).
+    setHref exit "https://github.com/ghcjs/ghcjs-dom-hello"
+    _ <- on exit click $ preventDefault >> liftIO (putMVar exitMVar ())
+
+    -- Force all all the lazy JSaddle evaluation to be executed
     syncPoint
 
-    -- In GHC compiled version the WebSocket connection will end when this
-    -- thread ends.  So we will wait until the user clicks exit.
+    -- Wait until the user clicks exit.
     liftIO $ takeMVar exitMVar
-    setInnerHTML body (Just "<h1>Ka kite ano (See you later)</h1>")
-    return ()
+    setInnerHTML body "<h1>Ka kite ano (See you later)</h1>"
diff --git a/src/Main.hs b/src/Main.hs
deleted file mode 100644
--- a/src/Main.hs
+++ /dev/null
@@ -1,18 +0,0 @@
-{-# LANGUAGE CPP #-}
-module Main (
-    main
-) where
-
-import HelloMain (helloMain)
-#if defined(ghcjs_HOST_OS)
-run :: a -> a
-run = id
-#elif defined(MIN_VERSION_jsaddle_wkwebview)
-import Language.Javascript.JSaddle.WKWebView (run)
-#else
-import Language.Javascript.JSaddle.WebKitGTK (run)
-#endif
-
-main :: IO ()
-main = run helloMain
-
diff --git a/src/WKWebView.hs b/src/WKWebView.hs
deleted file mode 100644
--- a/src/WKWebView.hs
+++ /dev/null
@@ -1,9 +0,0 @@
-module Main (
-    main
-) where
-
-import Language.Javascript.JSaddle.WKWebView (run)
-import HelloMain (helloMain)
-
-main :: IO ()
-main = run helloMain
diff --git a/src/Warp.hs b/src/Warp.hs
deleted file mode 100644
--- a/src/Warp.hs
+++ /dev/null
@@ -1,13 +0,0 @@
-module Main (
-    main
-) where
-
-import System.IO (stdout, hFlush)
-import Language.Javascript.JSaddle.Warp (run)
-import HelloMain (helloMain)
-
-main :: IO ()
-main = do
-  putStrLn "<a href=\"http://localhost:3708/\">http://localhost:3708/</a>"
-  hFlush stdout
-  run 3708 helloMain
diff --git a/src/WebKitGTK.hs b/src/WebKitGTK.hs
deleted file mode 100644
--- a/src/WebKitGTK.hs
+++ /dev/null
@@ -1,9 +0,0 @@
-module Main (
-    main
-) where
-
-import Language.Javascript.JSaddle.WebKitGTK (run)
-import HelloMain (helloMain)
-
-main :: IO ()
-main = run helloMain
