diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+Copyright (c) 2010-2012 Hamish Mackenzie, Victor Nazarov, Luite Stegeman
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,6 @@
+#!/usr/bin/runhaskell 
+> module Main where
+> import Distribution.Simple
+> main :: IO ()
+> main = defaultMain
+
diff --git a/jsaddle-webkitgtk.cabal b/jsaddle-webkitgtk.cabal
new file mode 100644
--- /dev/null
+++ b/jsaddle-webkitgtk.cabal
@@ -0,0 +1,41 @@
+name: jsaddle-webkitgtk
+version: 0.8.0.0
+cabal-version: >=1.10
+build-type: Simple
+license: MIT
+license-file: LICENSE
+maintainer: Hamish Mackenzie <Hamish.K.Mackenzie@googlemail.com>
+synopsis: Interface for JavaScript that works with GHCJS and GHC
+description:
+    This package provides an EDSL for calling JavaScript that
+    can be used both from GHCJS and GHC.  When using GHC
+    the application is run using Warp and WebSockets to
+    drive a small JavaScipt helper.
+category: Web, Javascript
+author: Hamish Mackenzie
+
+source-repository head
+    type: git
+    location: https://github.com/ghcjs/jsaddle
+
+library
+    exposed-modules:
+        Language.Javascript.JSaddle.WebKitGTK
+    build-depends:
+        aeson >=0.8.0.2 && <1.1,
+        base <5,
+        bytestring >=0.10.6.0 && <0.11,
+        directory >=1.0.0.2 && <1.3,
+        gi-glib >=2.0.6 && <2.1,
+        gi-gtk >=3.0.6 && <3.1,
+        gi-webkit >=3.0.6 && <3.1,
+        gi-javascriptcore >=3.0.6 && <3.1,
+        haskell-gi-base >=0.20 && <0.21,
+        jsaddle >=0.8.0.0 && <0.9,
+        text >=1.2.1.3 && <1.3,
+        unix >=2.3.1.0 && <2.8,
+        webkitgtk3-javascriptcore >=0.14.0.0 && <0.15
+    default-language: Haskell2010
+    hs-source-dirs: src
+    ghc-options: -ferror-spans -Wall
+
diff --git a/src/Language/Javascript/JSaddle/WebKitGTK.hs b/src/Language/Javascript/JSaddle/WebKitGTK.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Javascript/JSaddle/WebKitGTK.hs
@@ -0,0 +1,211 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE LambdaCase #-}
+-----------------------------------------------------------------------------
+--
+-- Module      :  Language.Javascript.JSaddle.WebSockets
+-- Copyright   :  (c) Hamish Mackenzie
+-- License     :  MIT
+--
+-- Maintainer  :  Hamish Mackenzie <Hamish.K.Mackenzie@googlemail.com>
+--
+-- |
+--
+-----------------------------------------------------------------------------
+module Language.Javascript.JSaddle.WebKitGTK (
+  -- * Running JSM in a WebView
+    run
+  , runInWebView
+  ) where
+
+import Control.Monad (when, void)
+import qualified Control.Exception as E (catch)
+import Control.Exception (SomeException(..))
+import Control.Concurrent (forkIO, yield)
+
+import System.Posix.Signals (installHandler)
+import System.Directory (getCurrentDirectory)
+
+import Data.Monoid ((<>))
+import Data.ByteString.Lazy (toStrict, fromStrict)
+import qualified Data.ByteString.Lazy as LB (ByteString)
+import Data.Aeson (encode, decode)
+import Data.Text (Text)
+import qualified Data.Text as T (unpack, pack)
+import Data.Text.Foreign (useAsPtr, fromPtr)
+import Data.Text.Encoding (decodeUtf8, encodeUtf8)
+
+import Foreign.Ptr (castPtr, nullPtr)
+import Foreign.Marshal.Array (withArray, peekArray)
+import Foreign.Storable (Storable(..))
+import Foreign.Marshal.Alloc (alloca)
+
+import Data.GI.Base.ManagedPtr (withManagedPtr)
+import GI.GLib
+       (timeoutAdd, idleAdd, pattern PRIORITY_HIGH, pattern PRIORITY_DEFAULT)
+import qualified GI.Gtk as Gtk (main, init)
+import GI.Gtk
+       (windowSetPosition, windowSetDefaultSize, windowNew, scrolledWindowNew,
+        noAdjustment, containerAdd, WindowType(..), WindowPosition(..),
+        widgetDestroy, widgetGetToplevel, widgetShowAll, onWidgetDestroy,
+        mainQuit)
+import GI.JavaScriptCore.Structs.GlobalContext (GlobalContext(..))
+import GI.WebKit
+       (WebView, webViewGetMainFrame, webFrameGetGlobalContext,
+        onWebInspectorInspectWebView, webViewGetInspector, webViewSetSettings,
+        setWebSettingsEnableDeveloperExtras,
+        setWebSettingsEnableUniversalAccessFromFileUris,
+        webViewGetSettings, webViewNew, onWebViewLoadFinished,
+        webViewLoadString)
+
+import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSBase
+       (JSValueRef, JSValueRefRef, JSObjectRef, JSContextRef,
+        jsevaluatescript, JSStringRef)
+import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSStringRef
+       (jsstringretain, jsstringrelease, jsstringgetcharactersptr,
+        jsstringgetlength, jsstringcreatewithcharacters)
+import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSObjectRef
+       (jsobjectcallasfunction, JSCSize, jsobjectsetproperty,
+        jsobjectmakefunctionwithcallback, mkJSObjectCallAsFunctionCallback)
+import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSContextRef
+       (jscontextgetglobalobject)
+import Graphics.UI.Gtk.WebKit.JavaScriptCore.JSValueRef
+       (jsvalueprotect, jsvalueunprotect,
+        jsvaluetostringcopy, jsvaluemakestring, jsvaluemakeundefined)
+
+import Language.Javascript.JSaddle (JSM, Results)
+import Language.Javascript.JSaddle.Run (runJavaScript)
+import Language.Javascript.JSaddle.Run.Files (initState, runBatch, ghcjsHelpers)
+
+quitWebView :: WebView -> IO ()
+quitWebView wv = postGUIAsync $ do w <- widgetGetToplevel wv --TODO: Shouldn't this be postGUISync?
+                                   widgetDestroy w
+
+installQuitHandler :: WebView -> IO ()
+installQuitHandler wv = void $ installHandler keyboardSignal (Catch (quitWebView wv)) Nothing
+
+postGUIAsync :: IO () -> IO ()
+postGUIAsync action =
+  void . idleAdd PRIORITY_DEFAULT $ action >> return False
+
+withJSString :: Text -> (JSStringRef -> IO a) -> IO a
+withJSString s f = do
+    jsstring <- useAsPtr s $ \p l -> jsstringcreatewithcharacters (castPtr p) (fromIntegral l)
+    _ <- jsstringretain jsstring
+    result <- f jsstring
+    jsstringrelease jsstring
+    return result
+
+withJSContextRef :: GlobalContext -> (JSContextRef -> IO a) -> IO a
+withJSContextRef (GlobalContext ctx) f = withManagedPtr ctx (f . castPtr)
+
+valueToText :: JSContextRef -> JSValueRef -> IO Text
+valueToText ctxRef s = do
+    jsstring <- jsvaluetostringcopy ctxRef s nullPtr
+    l <- jsstringgetlength jsstring
+    p <- jsstringgetcharactersptr jsstring
+    result <- fromPtr (castPtr p) (fromIntegral l)
+    jsstringrelease jsstring
+    return result
+
+check :: JSContextRef -> (JSValueRefRef -> IO a) -> IO a
+check ctxRef f =
+    alloca $ \exceptionPtr -> do
+        poke exceptionPtr nullPtr
+        result <- f exceptionPtr
+        exception <- peek exceptionPtr
+        when (exception /= nullPtr) $ do
+            errorText <- valueToText ctxRef exception
+            error $ T.unpack errorText
+        return result
+
+eval :: JSContextRef -> Text -> IO JSValueRef
+eval ctxRef script =
+    withJSString script $ \script' ->
+        check ctxRef $ jsevaluatescript ctxRef script' nullPtr nullPtr 0
+
+run :: JSM () -> IO ()
+run main = do
+    _ <- Gtk.init Nothing
+    window <- windowNew WindowTypeToplevel
+    _ <- timeoutAdd PRIORITY_HIGH 10 (yield >> return True)
+    windowSetDefaultSize window 900 600
+    windowSetPosition window WindowPositionCenter
+    scrollWin <- scrolledWindowNew noAdjustment noAdjustment
+    webView <- webViewNew
+    settings <- webViewGetSettings webView
+    setWebSettingsEnableUniversalAccessFromFileUris settings True
+    setWebSettingsEnableDeveloperExtras settings True
+    webViewSetSettings webView settings
+    window `containerAdd` scrollWin
+    scrollWin `containerAdd` webView
+    _ <- onWidgetDestroy window mainQuit
+    widgetShowAll window
+    inspector <- webViewGetInspector webView
+    _ <- onWebInspectorInspectWebView inspector $ \_ -> do
+        inspectorWindow <- windowNew WindowTypeToplevel
+        windowSetDefaultSize inspectorWindow 900 600
+        inspectorScrollWin <- scrolledWindowNew noAdjustment noAdjustment
+        inspectorWebView <- webViewNew
+        inspectorWindow `containerAdd` inspectorScrollWin
+        inspectorScrollWin `containerAdd` inspectorWebView
+        widgetShowAll inspectorWindow
+        return inspectorWebView
+    pwd <- getCurrentDirectory
+    void . onWebViewLoadFinished webView $ \ _ ->
+        runInWebView main webView
+    webViewLoadString webView "" "text/html" "UTF-8" $ "file://" <> T.pack pwd <> "/"
+    installQuitHandler webView
+    Gtk.main
+
+runInWebView :: JSM () -> WebView -> IO ()
+runInWebView f webView = do
+    ctx <- webViewGetMainFrame webView >>= webFrameGetGlobalContext
+    runJSaddleBatch <-
+        withJSContextRef ctx $ \ctxRef -> do
+            result <- eval ctxRef (decodeUtf8 $ toStrict jsaddleJs)
+            jsvalueprotect ctxRef result
+            return result
+
+    (processResults, start) <- runJavaScript (\batch -> postGUIAsync $
+        withJSContextRef ctx $ \ctxRef ->
+            withJSString (decodeUtf8 . toStrict $ encode batch) $ \script -> do
+                val <- jsvaluemakestring ctxRef script
+                withArray [val] $ \args ->
+                    void . check ctxRef $ jsobjectcallasfunction ctxRef runJSaddleBatch nullPtr 1 args
+                jsvalueunprotect ctxRef val)
+        f
+
+    withJSContextRef ctx $ \ctxRef -> do
+        addJSaddleHandler ctxRef processResults
+        void $ forkIO start
+
+addJSaddleHandler :: JSContextRef -> (Results -> IO ()) -> IO ()
+addJSaddleHandler ctxRef processResult = do
+    callback <- mkJSObjectCallAsFunctionCallback wrap
+    function <- jsobjectmakefunctionwithcallback ctxRef nullPtr callback
+    global <- jscontextgetglobalobject ctxRef
+    withJSString "jsaddleCallback" $ \propName ->
+        jsobjectsetproperty ctxRef global propName function 0 nullPtr
+  where
+    wrap :: JSContextRef -> JSObjectRef -> JSObjectRef -> JSCSize -> JSValueRefRef -> JSValueRefRef -> IO JSValueRef
+    wrap _ctx _fobj _this argc argv exception = do
+            [arg] <- peekArray (fromIntegral argc) argv
+            bs <- encodeUtf8 <$> valueToText ctxRef arg
+            mapM_ processResult (decode (fromStrict bs))
+            jsvaluemakeundefined ctxRef
+      `E.catch` \(e :: SomeException) -> do
+            withJSString (T.pack (show e)) (jsvaluemakestring ctxRef) >>= poke exception
+            jsvaluemakeundefined ctxRef
+
+jsaddleJs :: LB.ByteString
+jsaddleJs = ghcjsHelpers <> "\
+    \(function() {\n\
+    \ " <> initState <> "\n\
+    \ return function(batchJSON) {\n\
+    \  var batch = JSON.parse(batchJSON);\n\
+    \ " <> runBatch (\a -> "window.jsaddleCallback(JSON.stringify(" <> a <> "));") <> "\
+    \ };\n\
+    \})()\n\
+    \"
