diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,25 @@
+## Changelog for the `threepenny-gui` package
+
+**0.4.0.0** -- Snapshot release.
+
+* New `UI` monad for easier JavaScript FFI and recursion in FRP.
+* Garbage collection for DOM elements. (Unfortunately, this doesn't support using custom HTML files anymore, see [issue #60][60].)
+* First stab at widgets.
+* Update dependency to `websockets-0.8`.
+
+**0.3.0.0** -- Snapshot release.
+
+* Browser communication with WebSockets.
+* First stab at FRP integration.
+
+**0.2.0.0** -- Snapshot release.
+
+* First stab at easy JavaScript FFI.
+
+**0.1.0.0**
+
+* Initial release.
+
+
+
+  [60]: https://github.com/HeinrichApfelmus/threepenny-gui/issues/60
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,3 +1,16 @@
+The following license ("BSD3") applies to almost all files in this project,
+in particular the source code indicated in the `threepenny-gui.cabal` file.
+Exceptions are audio sample (*.wav) files,
+and files whose content explicitely indicates a different license.
+
+--
+
+Copyright (c) 2013, Heinrich Apfelmus <https://github.com/HeinrichApfelmus/>
+Copyright (c) 2013, Daniel Austin     <https://github.com/daniel-r-austin>
+Copyright (c) 2013, Daniel Mlot       <https://github.com/duplode>
+Copyright (c) 2013, Rnons             <https://github.com/rnons>
+Copyright (c) 2012, Jeremy Bowers     <https://github.com/thejerf>
+Copyright (c) 2011-2012, Chris Done   <https://github.com/chrisdone>
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/samples/BarTab.hs b/samples/BarTab.hs
new file mode 100644
--- /dev/null
+++ b/samples/BarTab.hs
@@ -0,0 +1,77 @@
+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
+
+import Control.Applicative
+import Control.Monad
+import Data.IORef
+import Data.Maybe
+
+import qualified Graphics.UI.Threepenny as UI
+import Graphics.UI.Threepenny.Core
+
+
+-- | Main entry point.
+main :: IO ()
+main = startGUI defaultConfig { tpPort = 10000 } setup
+
+setup :: Window -> UI ()
+setup w = do
+    -- active elements
+    return w # set title "BarTab"
+
+    elAdd    <- UI.button # set UI.text "Add"
+    elRemove <- UI.button # set UI.text "Remove"
+    elResult <- UI.span
+
+    inputs   <- liftIO $ newIORef []
+    
+    -- functionality
+    let
+        displayTotal = void $ do
+            xs <- getValuesList =<< liftIO (readIORef inputs)
+            element elResult # set text (showNumber . sum $ map readNumber xs)
+        
+        redoLayout :: UI ()
+        redoLayout = void $ do
+            layout <- mkLayout =<< liftIO (readIORef inputs)
+            getBody w # set children [layout]
+            displayTotal
+
+        mkLayout :: [Element] -> UI Element
+        mkLayout xs = column $
+            [row [element elAdd, element elRemove]
+            ,UI.hr]
+            ++ map element xs ++
+            [UI.hr
+            ,row [UI.span # set text "Sum: ", element elResult]
+            ]
+        
+        addInput :: UI ()
+        addInput = do
+            elInput <- UI.input # set value "0"
+            on (domEvent "livechange") elInput $ \_ -> displayTotal
+            liftIO $ modifyIORef inputs (elInput:)
+        
+        removeInput :: UI ()
+        removeInput = liftIO $ modifyIORef inputs (drop 1)
+    
+    on UI.click elAdd    $ \_ -> addInput    >> redoLayout
+    on UI.click elRemove $ \_ -> removeInput >> redoLayout
+    addInput >> redoLayout
+
+
+{-----------------------------------------------------------------------------
+    Functionality
+------------------------------------------------------------------------------}
+type Number = Maybe Double
+
+instance Num Number where
+    (+) = liftA2 (+)
+    (-) = liftA2 (-)
+    (*) = liftA2 (*)
+    abs = fmap abs
+    signum = fmap signum
+    fromInteger = pure . fromInteger
+
+readNumber :: String -> Number
+readNumber s = listToMaybe [x | (x,"") <- reads s]    
+showNumber   = maybe "--" show
diff --git a/samples/Buttons.hs b/samples/Buttons.hs
new file mode 100644
--- /dev/null
+++ b/samples/Buttons.hs
@@ -0,0 +1,78 @@
+import Control.Monad
+import Control.Concurrent (threadDelay)
+
+import Paths
+
+import qualified Graphics.UI.Threepenny as UI
+import Graphics.UI.Threepenny.Core
+
+{-----------------------------------------------------------------------------
+    Buttons
+------------------------------------------------------------------------------}
+
+main :: IO ()
+main = do
+    static <- getStaticDir
+    startGUI defaultConfig
+        { tpPort       = 10000
+        , tpStatic     = Just static
+        } setup
+
+setup :: Window -> UI ()
+setup w = void $ do
+    return w # set title "Buttons"
+    UI.addStyleSheet w "buttons.css"
+
+    buttons <- mkButtons
+    getBody w #+
+        [UI.div #. "wrap" #+ (greet ++ map element buttons ++ [viewSource])]
+
+greet :: [UI Element]
+greet =
+    [ UI.h1  #+ [string "Hello, Haskell!"]
+    , UI.div #+ [string "Try the buttons below, they hover and click."]
+    ]
+
+
+mkButton :: String -> UI (Element, Element)
+mkButton title = do
+    button <- UI.button #. "button" #+ [string title]
+    view   <- UI.p #+ [element button]
+    return (button, view)
+
+mkButtons :: UI [Element]
+mkButtons = do
+    list    <- UI.ul #. "buttons-list"
+    
+    (button1, view1) <- mkButton button1Title
+    
+    on UI.hover button1 $ \_ -> do
+        element button1 # set text (button1Title ++ " [hover]")
+    on UI.leave button1 $ \_ -> do
+        element button1 # set text button1Title
+    on UI.click button1 $ \_ -> do
+        element button1 # set text (button1Title ++ " [pressed]")
+        liftIO $ threadDelay $ 1000 * 1000 * 1
+        element list    #+ [UI.li # set html "<b>Delayed</b> result!"]
+    
+    (button2, view2) <- mkButton button2Title
+
+    on UI.hover button2 $ \_ -> do
+        element button2 # set text (button2Title ++ " [hover]")
+    on UI.leave button2 $ \_ -> do
+        element button2 # set text button2Title
+    on UI.click button2 $ \_ -> do
+        element button2 # set text (button2Title ++ " [pressed]")
+        element list    #+ [UI.li # set html "Zap! Quick result!"]
+    
+    return [list, view1, view2]
+
+  where button1Title = "Click me, I delay a bit"
+        button2Title = "Click me, I work immediately"
+
+viewSource :: UI Element
+viewSource = UI.p #+
+    [UI.anchor #. "view-source" # set UI.href url #+ [string "View source code"]]
+    where
+    url = "https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/Buttons.hs"
+
diff --git a/samples/CRUD.hs b/samples/CRUD.hs
new file mode 100644
--- /dev/null
+++ b/samples/CRUD.hs
@@ -0,0 +1,138 @@
+{-----------------------------------------------------------------------------
+    threepenny-gui
+    
+    Example:
+    Small database with CRUD operations and filtering.
+    To keep things simple, the list box is rebuild every time
+    that the database is updated. This is perfectly fine for rapid prototyping.
+    A more sophisticated approach would use incremental updates.
+------------------------------------------------------------------------------}
+{-# LANGUAGE RecursiveDo #-}
+
+import Prelude hiding (lookup)
+import Control.Monad  (void)
+import Data.List      (isPrefixOf)
+import Data.Maybe
+import Data.Monoid
+import qualified Data.Map as Map
+import qualified Data.Set as Set
+
+import qualified Graphics.UI.Threepenny as UI
+import Graphics.UI.Threepenny.Core hiding (delete)
+
+{-----------------------------------------------------------------------------
+    Main
+------------------------------------------------------------------------------}
+main :: IO ()
+main = startGUI defaultConfig { tpPort = 10000 } setup
+
+setup :: Window -> UI ()
+setup window = void $ mdo
+    return window # set title "CRUD Example (Simple)"
+
+    -- GUI elements
+    createBtn   <- UI.button #+ [string "Create"]
+    deleteBtn   <- UI.button #+ [string "Delete"]
+    listBox     <- UI.listBox  bListBoxItems bSelection bDisplayDataItem
+    filterEntry <- UI.entry    bFilterString
+    ((firstname, lastname), tDataItem)
+                <- dataItem    bSelectionDataItem
+
+    -- GUI layout
+    element listBox # set (attr "size") "10" # set style [("width","200px")]
+    
+    let uiDataItem = grid [[string "First Name:", element firstname]
+                          ,[string "Last Name:" , element lastname]]
+    let glue = string " "
+    getBody window #+ [grid
+        [[row [string "Filter prefix:", element filterEntry], glue]
+        ,[element listBox, uiDataItem]
+        ,[row [element createBtn, element deleteBtn], glue]
+        ]]
+
+    -- events and behaviors
+    bFilterString <- stepper "" . rumors $ UI.userText filterEntry
+    let tFilter = isPrefixOf <$> UI.userText filterEntry
+        bFilter = facts  tFilter
+        eFilter = rumors tFilter
+
+    let eSelection  = rumors $ UI.userSelection listBox
+        eDataItemIn = rumors $ tDataItem
+        eCreate     = UI.click createBtn
+        eDelete     = UI.click deleteBtn
+
+    -- database
+    -- bDatabase :: Behavior (Database DataItem)
+    let update' mkey x = flip update x <$> mkey
+    bDatabase <- accumB emptydb $ concatenate <$> unions
+        [ create ("Emil","Example") <$ eCreate
+        , filterJust $ update' <$> bSelection <@> eDataItemIn
+        , delete <$> filterJust (bSelection <@ eDelete)
+        ]
+
+    -- selection
+    -- bSelection :: Behavior (Maybe DatabaseKey)
+    bSelection <- stepper Nothing $ head <$> unions
+        [ eSelection
+        , Nothing <$ eDelete
+        , Just . nextKey <$> bDatabase <@ eCreate
+        , (\b s p -> b >>= \a -> if p (s a) then Just a else Nothing)
+            <$> bSelection <*> bShowDataItem <@> eFilter
+        ]
+                
+    let bLookup :: Behavior (DatabaseKey -> Maybe DataItem)
+        bLookup = flip lookup <$> bDatabase
+                
+        bShowDataItem :: Behavior (DatabaseKey -> String)
+        bShowDataItem = (maybe "" showDataItem .) <$> bLookup
+
+        bDisplayDataItem = (UI.string .) <$> bShowDataItem
+                
+        bListBoxItems :: Behavior [DatabaseKey]
+        bListBoxItems = (\p show -> filter (p. show) . keys)
+                    <$> bFilter <*> bShowDataItem <*> bDatabase
+
+        bSelectionDataItem :: Behavior (Maybe DataItem)
+        bSelectionDataItem = (=<<) <$> bLookup <*> bSelection
+
+    -- automatically enable / disable editing
+    let
+        bDisplayItem :: Behavior Bool
+        bDisplayItem = maybe False (const True) <$> bSelection
+    
+    element deleteBtn # sink UI.enabled bDisplayItem
+    element firstname # sink UI.enabled bDisplayItem
+    element lastname  # sink UI.enabled bDisplayItem
+
+
+{-----------------------------------------------------------------------------
+    Database Model
+------------------------------------------------------------------------------}
+type DatabaseKey = Int
+data Database a  = Database { nextKey :: !Int, db :: Map.Map DatabaseKey a }
+
+emptydb = Database 0 Map.empty
+keys    = Map.keys . db
+
+create x     (Database newkey db) = Database (newkey+1) $ Map.insert newkey x db
+update key x (Database newkey db) = Database newkey     $ Map.insert key    x db
+delete key   (Database newkey db) = Database newkey     $ Map.delete key db
+lookup key   (Database _      db) = Map.lookup key db
+
+{-----------------------------------------------------------------------------
+    Data items that are stored in the data base
+------------------------------------------------------------------------------}
+type DataItem = (String, String)
+showDataItem (firstname, lastname) = lastname ++ ", " ++ firstname
+
+-- | Data item widget, consisting of two text entries
+dataItem
+    :: Behavior (Maybe DataItem)
+    -> UI ((Element, Element), Tidings DataItem)
+dataItem bItem = do
+    entry1 <- UI.entry $ fst . maybe ("","") id <$> bItem
+    entry2 <- UI.entry $ snd . maybe ("","") id <$> bItem
+    
+    return ( (getElement entry1, getElement entry2)
+           , (,) <$> UI.userText entry1 <*> UI.userText entry2
+           )
diff --git a/samples/Chat.hs b/samples/Chat.hs
new file mode 100644
--- /dev/null
+++ b/samples/Chat.hs
@@ -0,0 +1,106 @@
+import Control.Concurrent
+import qualified Control.Concurrent.Chan as Chan
+import Control.Exception
+import Control.Monad
+import Data.Functor
+import Data.List.Extra
+import Data.Time
+import Data.IORef
+import Prelude hiding (catch)
+
+import Paths
+
+import qualified Graphics.UI.Threepenny as UI
+import Graphics.UI.Threepenny.Core hiding (text)
+
+{-----------------------------------------------------------------------------
+    Chat
+------------------------------------------------------------------------------}
+
+main :: IO ()
+main = do
+    static   <- getStaticDir
+    messages <- Chan.newChan
+    startGUI defaultConfig
+        { tpPort       = 10000
+        , tpCustomHTML = Just "chat.html"
+        , tpStatic     = Just static
+        } $ setup messages
+
+type Message = (UTCTime, String, String)
+
+setup :: Chan Message -> Window -> UI ()
+setup globalMsgs window = do
+    msgs <- liftIO $ Chan.dupChan globalMsgs
+
+    return window # set title "Chat"
+    
+    (nickRef, nickname) <- mkNickname
+    messageArea         <- mkMessageArea msgs nickRef
+
+    getBody window #+
+        [ UI.div #. "header"   #+ [string "Threepenny Chat"]
+        , UI.div #. "gradient"
+        , viewSource
+        , element nickname
+        , element messageArea
+        ]
+    
+    messageReceiver <- liftIO $ forkIO $ receiveMessages window msgs messageArea
+
+    on UI.disconnect window $ const $ liftIO $ do
+        killThread messageReceiver
+        now   <- getCurrentTime
+        nick  <- readIORef nickRef
+        Chan.writeChan msgs (now,nick,"( left the conversation )")
+
+
+receiveMessages w msgs messageArea = do
+    messages <- Chan.getChanContents msgs
+    forM_ messages $ \msg -> do
+        atomic w $ runUI w $ do
+          -- FIXME: withWindow  should include a call to  atomic ?
+          element messageArea #+ [mkMessage msg]
+          UI.scrollToBottom messageArea
+
+mkMessageArea :: Chan Message -> IORef String -> UI Element
+mkMessageArea msgs nickname = do
+    input <- UI.textarea #. "send-textarea"
+    
+    on UI.sendValue input $ (. trim) $ \content -> do
+        element input # set value ""
+        when (not (null content)) $ liftIO $ do
+            now  <- getCurrentTime
+            nick <- readIORef nickname
+            when (not (null nick)) $
+                Chan.writeChan msgs (now,nick,content)
+
+    UI.div #. "message-area" #+ [UI.div #. "send-area" #+ [element input]]
+
+
+mkNickname :: UI (IORef String, Element)
+mkNickname = do
+    input  <- UI.input #. "name-input"
+    el     <- UI.div   #. "name-area"  #+
+                [ UI.span  #. "name-label" #+ [string "Your name "]
+                , element input
+                ]
+    UI.setFocus input
+    
+    nick <- liftIO $ newIORef ""
+    on UI.keyup input $ \_ -> liftIO . writeIORef nick . trim =<< get value input
+    return (nick,el)
+
+mkMessage :: Message -> UI Element
+mkMessage (timestamp, nick, content) =
+    UI.div #. "message" #+
+        [ UI.div #. "timestamp" #+ [string $ show timestamp]
+        , UI.div #. "name"      #+ [string $ nick ++ " says:"]
+        , UI.div #. "content"   #+ [string content]
+        ]
+
+viewSource :: UI Element
+viewSource =
+    UI.anchor #. "view-source" # set UI.href url #+ [string "View source code"]
+    where
+    url = "https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/Chat.hs"
diff --git a/samples/CurrencyConverter.hs b/samples/CurrencyConverter.hs
new file mode 100644
--- /dev/null
+++ b/samples/CurrencyConverter.hs
@@ -0,0 +1,40 @@
+import Control.Monad (void)
+import Data.Maybe
+import Text.Printf
+import Safe          (readMay)
+
+import qualified Graphics.UI.Threepenny as UI
+import Graphics.UI.Threepenny.Core
+
+{-----------------------------------------------------------------------------
+    Main
+------------------------------------------------------------------------------}
+main :: IO ()
+main = startGUI defaultConfig { tpPort = 10000 } setup
+
+setup :: Window -> UI ()
+setup window = void $ do
+    return window # set title "Currency Converter"
+
+    dollar <- UI.input
+    euro   <- UI.input
+    
+    getBody window #+ [
+            column [
+                grid [[string "Dollar:", element dollar]
+                     ,[string "Euro:"  , element euro  ]]
+            , string "Amounts update while typing."
+            ]]
+
+    euroIn   <- stepper "0" $ UI.valueChange euro
+    dollarIn <- stepper "0" $ UI.valueChange dollar
+    let
+        rate = 0.7 :: Double
+        withString f = maybe "-" (printf "%.2f") . fmap f . readMay
+    
+        dollarOut = withString (/ rate) <$> euroIn
+        euroOut   = withString (* rate) <$> dollarIn
+    
+    element euro   # sink value euroOut
+    element dollar # sink value dollarOut
+
diff --git a/samples/Data/List/Extra.hs b/samples/Data/List/Extra.hs
new file mode 100644
--- /dev/null
+++ b/samples/Data/List/Extra.hs
@@ -0,0 +1,8 @@
+module Data.List.Extra where
+                  
+import Data.List
+import Data.Char
+import Data.Maybe
+
+trim :: String -> String
+trim = reverse . dropWhile isSpace . reverse . dropWhile isSpace
diff --git a/samples/DragNDropExample.hs b/samples/DragNDropExample.hs
new file mode 100644
--- /dev/null
+++ b/samples/DragNDropExample.hs
@@ -0,0 +1,66 @@
+import Control.Applicative
+import Control.Monad
+import Data.IORef
+import Data.Maybe
+
+import Paths
+
+import qualified Graphics.UI.Threepenny as UI
+import Graphics.UI.Threepenny.Core
+
+{-----------------------------------------------------------------------------
+    Drag'N'Drop example
+------------------------------------------------------------------------------}
+main :: IO ()
+main = do
+    static <- getStaticDir
+    startGUI defaultConfig
+        { tpPort       = 10000
+        , tpStatic     = Just static
+        } setup
+
+setup :: Window -> UI ()
+setup w = void $ do
+    return w # set title "Drag 'N' Drop Example"
+    UI.addStyleSheet w "DragNDropExample.css"
+    
+    pairs <- sequence $
+        zipWith mkDragPair (words "red green blue") (map (150*) [0..2])
+    getBody w #+ concat [[element i, element o] | (i,o) <- pairs]
+
+type Color = String
+
+mkDragPair :: Color -> Int -> UI (Element, Element)
+mkDragPair color position = do
+    elDrag <- UI.new #. "box-drag"
+        # set UI.style [("left", show position ++ "px"), ("color",color)]
+        # set text "Drag me!"
+        # set UI.draggable True
+        # set UI.dragData color
+
+    elDrop  <- UI.new #. "box-drop"
+        # set UI.style [("border","2px solid " ++ color), ("left", show position ++ "px")]
+
+
+    dropSuccess <- liftIO $ newIORef False
+
+    on UI.dragStart elDrag $ \_ -> void $
+        element elDrop
+            # set text "Drop here!"
+            # set UI.droppable True
+    on UI.dragEnd   elDrag $ \_ -> void $ do
+        dropped <- liftIO $ readIORef dropSuccess
+        when (not dropped) $ void $
+            element elDrop
+                # set text ""
+                # set UI.droppable False
+
+    on UI.drop elDrop $ \color' -> when (color == color') $ void $ do
+        liftIO $ writeIORef dropSuccess True
+        delete elDrag
+        element elDrop
+            # set text "Dropped!"
+            # set UI.droppable False
+    
+    return (elDrag, elDrop)
+
diff --git a/samples/DrumMachine.hs b/samples/DrumMachine.hs
new file mode 100644
--- /dev/null
+++ b/samples/DrumMachine.hs
@@ -0,0 +1,93 @@
+import Control.Monad
+import Data.IORef
+import Data.Functor
+
+import Paths
+import System.FilePath
+
+import qualified Graphics.UI.Threepenny as UI
+import Graphics.UI.Threepenny.Core
+
+{-----------------------------------------------------------------------------
+    Configuration
+------------------------------------------------------------------------------}
+bars  = 4
+beats = 4
+defaultBpm = 120
+
+bpm2ms :: Int -> Int
+bpm2ms bpm = ceiling $ 1000*60 / fromIntegral bpm
+
+-- NOTE: Samples taken from "conductive-examples"
+
+instruments = words "kick snare hihat"
+
+loadInstrumentSample name = do
+    static <- liftIO $ getStaticDir
+    loadFile "audio/wav" (static </> name <.> "wav")
+
+{-----------------------------------------------------------------------------
+    Main
+------------------------------------------------------------------------------}
+main :: IO ()
+main = startGUI defaultConfig { tpPort = 10000 } setup
+
+setup :: Window -> UI ()
+setup w = void $ do
+    return w # set title "Ha-ha-ha-ks-ks-ks-ha-ha-ha-ell-ell-ell"
+
+    elBpm  <- UI.input # set value (show defaultBpm)
+    elTick <- UI.span
+    (kit, elInstruments) <- mkDrumKit
+    let status = grid [[UI.string "BPM:" , element elBpm]
+                      ,[UI.string "Beat:", element elTick]]
+    getBody w #+ [UI.div #. "wrap" #+ (status : map element elInstruments)]
+    
+    timer <- UI.timer # set UI.interval (bpm2ms defaultBpm)
+    eBeat <- accumE (0::Int) $
+        (\beat -> (beat + 1) `mod` (beats * bars)) <$ UI.tick timer
+    onEvent eBeat $ \beat -> do
+        -- display beat count
+        element elTick # set text (show $ beat + 1)
+        -- play corresponding sounds
+        sequence_ $ map (!! beat) kit
+    
+    -- allow user to set BPM
+    on UI.keydown elBpm $ \keycode -> when (keycode == 13) $ void $ do
+        bpm <- read <$> get value elBpm
+        return timer # set UI.interval (bpm2ms bpm)
+    
+    -- star the timer
+    UI.start timer
+
+
+type Kit        = [Instrument]
+type Instrument = [Beat]
+type Beat       = UI ()         -- play the corresponding sound
+
+mkDrumKit :: UI (Kit, [Element])
+mkDrumKit = unzip <$> mapM mkInstrument instruments
+
+mkInstrument :: String -> UI (Instrument, Element)
+mkInstrument name = do
+    elCheckboxes <-
+        sequence $ replicate bars  $
+        sequence $ replicate beats $
+            UI.input # set UI.type_ "checkbox"
+
+    url     <- loadInstrumentSample name
+    elAudio <- UI.audio # set (attr "preload") "1" # set UI.src url
+
+    let play box = do
+            checked <- get UI.checked box
+            when checked $ do
+                audioStop elAudio -- just in case the sound is already playing
+                audioPlay elAudio
+        beats    = map play . concat $ elCheckboxes
+        elGroups = [UI.span #. "bar" #+ map element bar | bar <- elCheckboxes]
+    
+    elInstrument <- UI.div #. "instrument"
+        #+ (element elAudio : UI.string name : elGroups)
+    
+    return (beats, elInstrument)
+
diff --git a/samples/MissingDollars.hs b/samples/MissingDollars.hs
new file mode 100644
--- /dev/null
+++ b/samples/MissingDollars.hs
@@ -0,0 +1,134 @@
+import Control.Monad
+import Safe
+
+import Paths
+
+import qualified Graphics.UI.Threepenny as UI
+import Graphics.UI.Threepenny.Core
+
+{-----------------------------------------------------------------------------
+    Missing Dollars
+------------------------------------------------------------------------------}
+main :: IO ()
+main = do
+    static <- getStaticDir
+    startGUI defaultConfig
+        { tpPort       = 10000
+        , tpStatic     = Just static
+        } setup
+
+
+setup :: Window -> UI ()
+setup w = void $ do
+    return w # set title "Missing Dollars"
+    UI.addStyleSheet w "missing-dollars.css"
+    
+    (headerView,headerMe) <- mkHeader
+    riddle                <- mkMissingDollarRiddle headerMe
+    let layout = [element headerView] ++ riddle ++ attributionSource        
+    getBody w #+ [UI.div #. "wrap" #+ layout]
+
+
+mkHeader :: UI (Element, Element)
+mkHeader = do
+    headerMe <- string "..."
+    view     <- UI.h1   #+ [string "The ", element headerMe, string " Dollars"]
+    return (view, headerMe)
+
+attributionSource :: [UI Element]
+attributionSource =
+    [ UI.p #+
+        [ UI.anchor #. "view-source" # set UI.href urlSource
+            #+ [string "View source code"]
+        ]
+    , UI.p #+
+        [ string "Originally by "
+        , UI.anchor # set UI.href urlAttribution #+ [string "Albert Lai"]
+        ]
+    ]
+  where
+    urlSource      = "https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/MissingDollars.hs"
+    urlAttribution = "http://www.vex.net/~trebla/humour/missing_dollar.html"
+
+
+mkMissingDollarRiddle :: Element -> UI [UI Element]
+mkMissingDollarRiddle headerMe = do
+    -- declare input and display values
+    (hotelOut : hotelCost : hotelHold : _)
+        <- sequence . replicate 3 $
+            UI.input # set (attr "size") "3" # set (attr "type") "text"
+
+    (hotelChange : hotelRet     : hotelBal : hotelPocket :
+     hotelBal2   : hotelPocket2 : hotelSum : hotelMe     : _)
+        <- sequence . replicate 8 $ UI.span
+    
+    -- update procedure
+    let updateDisplay out cost hold = do
+        let change = out - cost
+            ret    = change - hold
+            bal    = out - ret
+            sum    = bal + hold
+            diff   = sum - out
+        element hotelOut     # set value (show out)
+        element hotelCost    # set value (show cost)
+        element hotelHold    # set value (show hold)
+        element hotelChange  # set text  (show change)
+        element hotelRet     # set text  (show ret)
+        element hotelBal     # set text  (show bal)
+        element hotelPocket  # set text  (show hold)
+        element hotelBal2    # set text  (show bal)
+        element hotelPocket2 # set text  (show hold)
+        element hotelSum     # set text  (show sum)
+        
+        if diff >= 0
+           then do element hotelMe  # set text ("extra $" ++ show diff ++ " come from")
+                   element headerMe # set text "Extra"
+           else do element hotelMe  # set text ("missing $" ++ show (-diff) ++ " go")
+                   element headerMe # set text "Missing"
+        return ()
+    
+    -- initialize values
+    updateDisplay 30 25 2
+    
+    -- calculate button
+    calculate <- UI.button #+ [string "Calculate"]
+    on UI.click calculate $ \_ -> do
+        result <- mapM readMay `liftM` getValuesList [hotelOut,hotelCost,hotelHold]
+        case result of
+            Just [getout,getcost,gethold] -> updateDisplay getout getcost gethold
+            _ -> return ()
+    
+    return $
+        [ UI.h2 #+ [string "The Guests, The Bellhop, And The Pizza"]
+        , UI.p  #+
+            [ string "Three guests went to a hotel and gave $"
+            , element hotelOut
+            , string " to the bellhop to buy pizza. The pizza cost only $"
+            , element hotelCost
+            , string ". Of the $"
+            , element hotelChange
+            , string " change, the bellhop kept $"
+            , element hotelHold
+            , string " to himself and returned $"
+            , element hotelRet
+            , string " to the guests."
+            ]
+        , UI.p  #+
+            [ string "So the guests spent $"
+            , element hotelBal
+            , string ", and the bellhop pocketed $"
+            , element hotelPocket
+            , string ". Now "
+            , string "$"
+            , element hotelBal2
+            , string "+$"
+            , element hotelPocket2
+            , string "=$"
+            , element hotelSum
+            , string ". Where did the "
+            , element hotelMe
+            , string "?"
+            ]
+        , element calculate
+        ]    
+
diff --git a/samples/Paths.hs b/samples/Paths.hs
new file mode 100644
--- /dev/null
+++ b/samples/Paths.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE CPP#-}
+module Paths (getStaticDir) where
+
+import Control.Monad
+import System.FilePath
+
+#if CABAL
+-- using cabal
+import qualified Paths_threepenny_gui (getDataDir)
+
+getStaticDir :: IO FilePath
+getStaticDir = (</> "wwwroot") `liftM` Paths_threepenny_gui.getDataDir
+
+#else
+-- using GHCi
+
+getStaticDir :: IO FilePath
+getStaticDir = return "../wwwroot/"
+
+#endif
diff --git a/samples/Tidings.hs b/samples/Tidings.hs
new file mode 100644
--- /dev/null
+++ b/samples/Tidings.hs
@@ -0,0 +1,37 @@
+module Tidings (
+    -- * Synopsis
+    -- The 'Tidings' data type for composing user events.
+    --
+    -- See <http://apfelmus.nfshost.com/blog/2012/03/29-frp-three-principles-bidirectional-gui.html>
+    -- for more information.
+    
+    -- * Documentation
+    Tidings, tidings, facts, rumors,
+    ) where
+
+import Reactive.Threepenny
+
+-- | Data type representing a behavior 'facts'
+-- and suggestions to change it 'rumors'.
+data Tidings a = T { facts :: Behavior a, rumors :: Event a }
+
+-- | Smart constructor. Combine facts and rumors into 'Tidings'.
+tidings :: Behavior a -> Event a -> Tidings a
+tidings b e = T b e
+
+instance Functor Tidings where
+    fmap f (T b e) = T (fmap f b) (fmap f e)
+
+-- | The applicative instance combines 'rumors'
+-- and uses 'facts' when some of the 'rumors' are not available.
+instance Applicative Tidings where
+    pure x  = T (pure x) never
+    f <*> x = uncurry ($) <$> pair f x
+
+pair :: Tidings a -> Tidings b -> Tidings (a,b)
+pair (T bx ex) (T by ey) = T b e
+    where
+    b = (,) <$> bx <*> by
+    x = flip (,) <$> by <@> ex
+    y = (,) <$> bx <@> ey
+    e = unionWith (\(x,_) (_,y) -> (x,y)) x y
diff --git a/samples/UseWords.hs b/samples/UseWords.hs
new file mode 100644
--- /dev/null
+++ b/samples/UseWords.hs
@@ -0,0 +1,101 @@
+{-# LANGUAGE ViewPatterns #-}
+
+import Control.Applicative hiding ((<|>),many)
+import Control.Monad
+import Control.Arrow (second)
+import Data.Maybe
+import Text.Parsec
+import System.FilePath ((</>))
+
+import qualified Graphics.UI.Threepenny as UI
+import Graphics.UI.Threepenny.Core hiding (string, (<|>), many)
+import Paths
+
+{-----------------------------------------------------------------------------
+    GUI
+------------------------------------------------------------------------------}
+main :: IO ()
+main = do
+    static <- getStaticDir
+    startGUI defaultConfig
+        { tpPort       = 10000
+        , tpStatic     = Just static
+        } setup
+
+
+setup :: Window -> UI ()
+setup w = do
+    filename <- liftIO $ fmap (</> "and-then-haskell.txt") getStaticDir 
+    andthen  <- liftIO $ readFile filename
+    case parts filename andthen of
+        Left parseerror -> debug $ show parseerror
+        Right parts     -> void $ do
+            UI.addStyleSheet w "use-words.css"
+
+            let (header, Prelude.drop 2 -> rest) = splitAt 3 parts            
+            
+            (views1, vars1) <- renderParts header
+            (views2, vars2) <- renderParts rest
+            varChoices      <- mapM (renderVarChoice (vars1 ++ vars2)) vars
+        
+            getBody w #+
+                [ viewSource
+                , UI.div #. "wrap" #+ (
+                    [ UI.div #. "header" #+ map element views1
+                    , UI.ul  #. "vars"   #+ map element varChoices
+                    ]
+                    ++ map element views2 )
+                ]
+            
+type VariableViews = [(Name, Element)]
+
+renderVarChoice :: VariableViews -> Variable -> UI Element
+renderVarChoice views (label,(name,def)) = do
+    input <- UI.input #. "var-value" # set value def
+    
+    on (domEvent "livechange") input $ \(EventData xs) -> do
+        let s = concat $ catMaybes xs
+        forM_ (filter ((==name).fst) views) $ \(_,el) -> do
+            element el # set text s
+    
+    UI.li #+ [UI.string (label ++ ":"), element input]
+
+renderParts :: [Part] -> UI ([Element], VariableViews)
+renderParts parts = do
+    views <- mapM renderPart parts
+    let variables = [(var, view) | (Ref var, view) <- zip parts views]
+    return (views, variables)
+
+renderPart :: Part -> UI Element
+renderPart (Text str) = UI.div #. "text" #+ [UI.string str]
+renderPart (Ref  var) = UI.div #. "var"
+    # maybe (set text $ "{" ++ var ++ "}") (either (set html) (set text))
+            (lookup var templatevars)
+
+viewSource :: UI Element
+viewSource = UI.p #+
+    [UI.anchor #. "view-source" # set UI.href url #+ [UI.string "View source code"]]
+    where
+    url = "https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/UseWords.hs"
+
+{-----------------------------------------------------------------------------
+    Parsing
+------------------------------------------------------------------------------}
+type Name     = String
+type Variable = (String, (Name, String))
+
+templatevars = map (second Right . snd) vars ++ map (second Left) exts
+
+vars :: [Variable]
+vars = [("Favourite technology",("favourite-language","Haskell"))
+       ,("Technology used at work",("work-language","Python"))
+       ,("Cool forum",("bar","LtU"))
+       ,("Particular to technology",("particular-stuff","monads"))]
+exts = [("br","<br><br>")]
+
+data Part = Text String | Ref String deriving Show
+
+parts :: SourceName -> String -> Either ParseError [Part]
+parts = parse (many (ref <|> text)) where
+    text = Text <$> many1 (notFollowedBy (string "{") *> anyChar)
+    ref  = Ref  <$> (string "{" *> many1 (noneOf "}") <* (string "}"))
diff --git a/src/BarTab.hs b/src/BarTab.hs
deleted file mode 100644
--- a/src/BarTab.hs
+++ /dev/null
@@ -1,86 +0,0 @@
-{-# LANGUAGE CPP, PackageImports #-}
-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
-
-import Control.Applicative
-import Control.Monad
-import Data.IORef
-import Data.Maybe
-
-import Paths
-
-#ifdef CABAL
-import qualified "threepenny-gui" Graphics.UI.Threepenny as UI
-import "threepenny-gui" Graphics.UI.Threepenny.Core
-#else
-import qualified Graphics.UI.Threepenny as UI
-import Graphics.UI.Threepenny.Core
-#endif
-
--- | Main entry point. Starts a TP server.
-main :: IO ()
-main = do
-    static <- getStaticDir
-    startGUI defaultConfig
-        { tpPort       = 10000
-        , tpStatic     = Just static
-        } setup
-
-setup :: Window -> IO ()
-setup w = do
-    -- active elements
-    return w # set title "BarTab"
-
-    elAdd    <- UI.button # set UI.text "Add"
-    elRemove <- UI.button # set UI.text "Remove"
-    elResult <- UI.span
-
-    inputs   <- newIORef []
-    
-    -- functionality
-    let
-        displayTotal = void $ do
-            xs <- getValuesList =<< readIORef inputs
-            element elResult # set text (showNumber . sum $ map readNumber xs)
-        
-        redoLayout :: IO ()
-        redoLayout = void $ do
-            layout <- mkLayout =<< readIORef inputs
-            getBody w # set children [layout]
-            displayTotal
-
-        mkLayout :: [Element] -> IO Element
-        mkLayout xs = column $
-            [row [element elAdd, element elRemove]
-            ,UI.hr]
-            ++ map element xs ++
-            [UI.hr
-            ,row [UI.span # set text "Sum: ", element elResult]
-            ]
-        
-        addInput :: IO ()
-        addInput = do
-            elInput <- UI.input # set value "0"
-            on (domEvent "livechange") elInput $ \_ -> displayTotal
-            modifyIORef inputs (elInput:)
-    
-    on UI.click elAdd    $ \_ -> addInput                    >> redoLayout
-    on UI.click elRemove $ \_ -> modifyIORef inputs (drop 1) >> redoLayout
-    addInput >> redoLayout
-
-
-{-----------------------------------------------------------------------------
-    Functionality
-------------------------------------------------------------------------------}
-type Number = Maybe Double
-
-instance Num Number where
-    (+) = liftA2 (+)
-    (-) = liftA2 (-)
-    (*) = liftA2 (*)
-    abs = fmap abs
-    signum = fmap signum
-    fromInteger = pure . fromInteger
-
-readNumber :: String -> Number
-readNumber s = listToMaybe [x | (x,"") <- reads s]    
-showNumber   = maybe "--" show
diff --git a/src/Buttons.hs b/src/Buttons.hs
deleted file mode 100644
--- a/src/Buttons.hs
+++ /dev/null
@@ -1,84 +0,0 @@
-{-# LANGUAGE CPP, PackageImports #-}
-
-import Control.Monad
-import Control.Concurrent (threadDelay)
-
-#ifdef CABAL
-import qualified "threepenny-gui" Graphics.UI.Threepenny as UI
-import "threepenny-gui" Graphics.UI.Threepenny.Core
-#else
-import qualified Graphics.UI.Threepenny as UI
-import Graphics.UI.Threepenny.Core
-#endif
-import Paths
-
-{-----------------------------------------------------------------------------
-    Buttons
-------------------------------------------------------------------------------}
-
-main :: IO ()
-main = do
-    static <- getStaticDir
-    startGUI defaultConfig
-        { tpPort       = 10000
-        , tpStatic     = Just static
-        } setup
-
-setup :: Window -> IO ()
-setup w = void $ do
-    return w # set title "Buttons"
-    UI.addStyleSheet w "buttons.css"
-
-    buttons <- mkButtons
-    getBody w #+
-        [UI.div #. "wrap" #+ (greet ++ map element buttons ++ [viewSource])]
-
-greet :: [IO Element]
-greet =
-    [ UI.h1  #+ [string "Hello, Haskell!"]
-    , UI.div #+ [string "Try the buttons below, they hover and click."]
-    ]
-
-
-mkButton :: String -> IO (Element, Element)
-mkButton title = do
-    button <- UI.button #. "button" #+ [string title]
-    view   <- UI.p #+ [element button]
-    return (button, view)
-
-mkButtons :: IO [Element]
-mkButtons = do
-    list    <- UI.ul #. "buttons-list"
-    
-    (button1, view1) <- mkButton button1Title
-    
-    on UI.hover button1 $ \_ -> do
-        element button1 # set text (button1Title ++ " [hover]")
-    on UI.leave button1 $ \_ -> do
-        element button1 # set text button1Title
-    on UI.click button1 $ \_ -> do
-        element button1 # set text (button1Title ++ " [pressed]")
-        threadDelay $ 1000 * 1000 * 1
-        element list    #+ [UI.li # set html "<b>Delayed</b> result!"]
-    
-    (button2, view2) <- mkButton button2Title
-
-    on UI.hover button2 $ \_ -> do
-        element button2 # set text (button2Title ++ " [hover]")
-    on UI.leave button2 $ \_ -> do
-        element button2 # set text button2Title
-    on UI.click button2 $ \_ -> do
-        element button2 # set text (button2Title ++ " [pressed]")
-        element list    #+ [UI.li # set html "Zap! Quick result!"]
-    
-    return [list, view1, view2]
-
-  where button1Title = "Click me, I delay a bit"
-        button2Title = "Click me, I work immediately"
-
-viewSource :: IO Element
-viewSource = UI.p #+
-    [UI.anchor #. "view-source" # set UI.href url #+ [string "View source code"]]
-    where
-    url = "https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/Buttons.hs"
-
diff --git a/src/Chat.hs b/src/Chat.hs
deleted file mode 100644
--- a/src/Chat.hs
+++ /dev/null
@@ -1,116 +0,0 @@
-{-# LANGUAGE CPP, PackageImports #-}
-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
-
-import Control.Concurrent
-import qualified Control.Concurrent.Chan as Chan
-import Control.Exception
-import Control.Monad
-import Data.Functor
-import Data.List.Extra
-import Data.Time
-import Data.IORef
-import Prelude hiding (catch)
-
-import Control.Monad.Trans.Reader as Reader
-import Control.Monad.IO.Class
-
-#ifdef CABAL
-import qualified "threepenny-gui" Graphics.UI.Threepenny as UI
-import "threepenny-gui" Graphics.UI.Threepenny.Core hiding (text)
-#else
-import qualified Graphics.UI.Threepenny as UI
-import Graphics.UI.Threepenny.Core hiding (text)
-#endif
-import Paths
-
-{-----------------------------------------------------------------------------
-    Chat
-------------------------------------------------------------------------------}
-
-main :: IO ()
-main = do
-    static   <- getStaticDir
-    messages <- Chan.newChan
-    startGUI defaultConfig
-        { tpPort       = 10000
-        , tpCustomHTML = Just "chat.html"
-        , tpStatic     = Just static
-        } $ setup messages
-
-type Message = (UTCTime, String, String)
-
-setup :: Chan Message -> Window -> IO ()
-setup globalMsgs window = do
-    msgs <- Chan.dupChan globalMsgs
-
-    return window # set title "Chat"
-    
-    (nickRef, nickname) <- mkNickname
-    messageArea         <- mkMessageArea msgs nickRef
-
-    getBody window #+
-        [ UI.div #. "header"   #+ [string "Threepenny Chat"]
-        , UI.div #. "gradient"
-        , viewSource
-        , element nickname
-        , element messageArea
-        ]
-    
-    messageReceiver <- forkIO $ receiveMessages window msgs messageArea
-
-    on UI.disconnect window $ const $ do
-        putStrLn "Disconnected!"
-        killThread messageReceiver
-        now   <- getCurrentTime
-        nick  <- readIORef nickRef
-        Chan.writeChan msgs (now,nick,"( left the conversation )")
-
-
-receiveMessages w msgs messageArea = do
-    messages <- Chan.getChanContents msgs
-    forM_ messages $ \msg -> do
-        atomic w $ do
-          element messageArea #+ [mkMessage msg]
-          UI.scrollToBottom messageArea
-
-mkMessageArea :: Chan Message -> IORef String -> IO Element
-mkMessageArea msgs nickname = do
-    input <- UI.textarea #. "send-textarea"
-    
-    on UI.sendValue input $ (. trim) $ \content -> do
-        when (not (null content)) $ do
-            now  <- getCurrentTime
-            nick <- readIORef nickname
-            element input # set value ""
-            when (not (null nick)) $
-                Chan.writeChan msgs (now,nick,content)
-
-    UI.div #. "message-area" #+ [UI.div #. "send-area" #+ [element input]]
-
-
-mkNickname :: IO (IORef String, Element)
-mkNickname = do
-    input  <- UI.input #. "name-input"
-    el     <- UI.div   #. "name-area"  #+
-                [ UI.span  #. "name-label" #+ [string "Your name "]
-                , element input
-                ]
-    UI.setFocus input
-    
-    nick <- newIORef ""
-    on UI.keyup input $ \_ -> writeIORef nick . trim =<< get value input
-    return (nick,el)
-
-mkMessage :: Message -> IO Element
-mkMessage (timestamp, nick, content) =
-    UI.div #. "message" #+
-        [ UI.div #. "timestamp" #+ [string $ show timestamp]
-        , UI.div #. "name"      #+ [string $ nick ++ " says:"]
-        , UI.div #. "content"   #+ [string content]
-        ]
-
-viewSource :: IO Element
-viewSource =
-    UI.anchor #. "view-source" # set UI.href url #+ [string "View source code"]
-    where
-    url = "https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/Chat.hs"
diff --git a/src/CurrencyConverter.hs b/src/CurrencyConverter.hs
deleted file mode 100644
--- a/src/CurrencyConverter.hs
+++ /dev/null
@@ -1,52 +0,0 @@
-{-----------------------------------------------------------------------------
-    threepenny-gui
-    
-    Example: Currency Converter
-------------------------------------------------------------------------------}
-{-# LANGUAGE CPP, PackageImports #-}
-
-import Control.Monad (void)
-import Data.Maybe
-import Text.Printf
-import Safe          (readMay)
-
-#ifdef CABAL
-import qualified "threepenny-gui" Graphics.UI.Threepenny as UI
-import "threepenny-gui" Graphics.UI.Threepenny.Core
-#else
-import qualified Graphics.UI.Threepenny as UI
-import Graphics.UI.Threepenny.Core
-#endif
-
-{-----------------------------------------------------------------------------
-    Main
-------------------------------------------------------------------------------}
-main :: IO ()
-main = startGUI defaultConfig { tpPort = 10000 } setup
-
-setup :: Window -> IO ()
-setup window = void $ do
-    return window # set title "Currency Converter"
-
-    dollar <- UI.input
-    euro   <- UI.input
-    
-    getBody window #+ [
-            column [
-                grid [[string "Dollar:", element dollar]
-                     ,[string "Euro:"  , element euro  ]]
-            , string "Amounts update while typing."
-            ]]
-
-    euroIn   <- stepper "0" $ UI.valueChange euro
-    dollarIn <- stepper "0" $ UI.valueChange dollar
-    let
-        rate = 0.7 :: Double
-        withString f = maybe "-" (printf "%.2f") . fmap f . readMay
-    
-        dollarOut = withString (/ rate) <$> euroIn
-        euroOut   = withString (* rate) <$> dollarIn
-    
-    element euro   # sink value euroOut
-    element dollar # sink value dollarOut
-
diff --git a/src/Data/List/Extra.hs b/src/Data/List/Extra.hs
deleted file mode 100644
--- a/src/Data/List/Extra.hs
+++ /dev/null
@@ -1,8 +0,0 @@
-module Data.List.Extra where
-                  
-import Data.List
-import Data.Char
-import Data.Maybe
-
-trim :: String -> String
-trim = reverse . dropWhile isSpace . reverse . dropWhile isSpace
diff --git a/src/DragNDropExample.hs b/src/DragNDropExample.hs
deleted file mode 100644
--- a/src/DragNDropExample.hs
+++ /dev/null
@@ -1,72 +0,0 @@
-{-# LANGUAGE CPP, PackageImports #-}
-
-import Control.Applicative
-import Control.Monad
-import Data.IORef
-import Data.Maybe
-
-#ifdef CABAL
-import qualified  "threepenny-gui" Graphics.UI.Threepenny as UI
-import "threepenny-gui" Graphics.UI.Threepenny.Core
-#else
-import qualified Graphics.UI.Threepenny as UI
-import Graphics.UI.Threepenny.Core
-#endif
-import Paths
-
-{-----------------------------------------------------------------------------
-    Drag'N'Drop example
-------------------------------------------------------------------------------}
-main :: IO ()
-main = do
-    static <- getStaticDir
-    startGUI defaultConfig
-        { tpPort       = 10000
-        , tpStatic     = Just static
-        } setup
-
-setup :: Window -> IO ()
-setup w = void $ do
-    return w # set title "Drag 'N' Drop Example"
-    UI.addStyleSheet w "DragNDropExample.css"
-    
-    pairs <- sequence $
-        zipWith (mkDragPair w) (words "red green blue") (map (150*) [0..2])
-    getBody w #+ concat [[element i, element o] | (i,o) <- pairs]
-
-type Color = String
-
-mkDragPair :: Window -> Color -> Int -> IO (Element, Element)
-mkDragPair w color position = do
-    elDrag <- UI.new #. "box-drag"
-        # set UI.style [("left", show position ++ "px"), ("color",color)]
-        # set text "Drag me!"
-        # set UI.draggable True
-        # set UI.dragData color
-
-    elDrop  <- UI.new #. "box-drop"
-        # set UI.style [("border","2px solid " ++ color), ("left", show position ++ "px")]
-
-
-    dropSuccess <- newIORef False
-
-    on UI.dragStart elDrag $ \_ -> void $
-        element elDrop
-            # set text "Drop here!"
-            # set UI.droppable True
-    on UI.dragEnd   elDrag $ \_ -> void $ do
-        dropped <- readIORef dropSuccess
-        when (not dropped) $ void $
-            element elDrop
-                # set text ""
-                # set UI.droppable False
-
-    on UI.drop elDrop $ \color' -> when (color == color') $ void $ do
-        writeIORef dropSuccess True
-        delete elDrag
-        element elDrop
-            # set text "Dropped!"
-            # set UI.droppable False
-    
-    return (elDrag, elDrop)
-
diff --git a/src/DrumMachine.hs b/src/DrumMachine.hs
deleted file mode 100644
--- a/src/DrumMachine.hs
+++ /dev/null
@@ -1,105 +0,0 @@
-{-# LANGUAGE CPP, PackageImports #-}
-
-import Control.Monad
-import Data.IORef
-import Data.Functor
-
-#ifdef CABAL
-import qualified "threepenny-gui" Graphics.UI.Threepenny as UI
-import "threepenny-gui" Graphics.UI.Threepenny.Core
-#else
-import qualified Graphics.UI.Threepenny as UI
-import Graphics.UI.Threepenny.Core
-#endif
-import Paths
-import System.FilePath
-
-{-----------------------------------------------------------------------------
-    Configuration
-------------------------------------------------------------------------------}
-bars  = 4
-beats = 4
-defaultBpm = 120
-
-bpm2ms :: Int -> Int
-bpm2ms bpm = ceiling $ 1000*60 / fromIntegral bpm
-
--- NOTE: Samples taken from "conductive-examples"
-
-instruments = words "kick snare hihat"
-
-loadInstrumentSample w name = do
-    static <- getStaticDir
-    loadFile w "audio/wav" (static </> name <.> "wav")
-
-{-----------------------------------------------------------------------------
-    Main
-------------------------------------------------------------------------------}
-main :: IO ()
-main = do
-    static <- getStaticDir
-    startGUI defaultConfig
-        { tpPort       = 10000
-        , tpStatic     = Just static
-        } setup
-
-setup :: Window -> IO ()
-setup w = void $ do
-    return w # set title "Ha-ha-ha-ks-ks-ks-ha-ha-ha-ell-ell-ell"
-
-    elBpm  <- UI.input # set value (show defaultBpm)
-    elTick <- UI.span
-    (kit, elInstruments) <- mkDrumKit w
-    let status = grid [[UI.string "BPM:" , element elBpm]
-                      ,[UI.string "Beat:", element elTick]]
-    getBody w #+ [UI.div #. "wrap" #+ (status : map element elInstruments)]
-    
-    timer <- UI.timer # set UI.interval (bpm2ms defaultBpm)
-    eBeat <- accumE (0::Int) $
-        (\beat -> (beat + 1) `mod` (beats * bars)) <$ UI.tick timer
-    _ <- register eBeat $ \beat -> do
-        -- display beat count
-        element elTick # set text (show $ beat + 1)
-        -- play corresponding sounds
-        sequence_ $ map (!! beat) kit
-    
-    -- allow user to set BPM
-    on UI.keydown elBpm $ \keycode -> when (keycode == 13) $ void $ do
-        bpm <- read <$> get value elBpm
-        return timer # set UI.interval (bpm2ms bpm)
-    
-    -- star the timer
-    UI.start timer
-
-
-type Kit        = [Instrument]
-type Instrument = [Beat]
-type Beat       = IO ()         -- play the corresponding sound
-
-mkDrumKit :: Window -> IO (Kit, [Element])
-mkDrumKit w = unzip <$> mapM (mkInstrument w) instruments
-
-mkInstrument :: Window -> String -> IO (Instrument, Element)
-mkInstrument window name = do
-    elCheckboxes <-
-        sequence $ replicate bars  $
-        sequence $ replicate beats $
-            UI.input # set UI.type_ "checkbox"
-
-    url     <- loadInstrumentSample window name
-    elAudio <- UI.audio # set (attr "preload") "1" # set UI.src url
-
-    let
-        play box = do
-            checked <- get UI.checked box
-            when checked $ do
-                audioStop elAudio -- just in case the sound is already playing
-                audioPlay elAudio
-        beats    = map play . concat $ elCheckboxes
-        elGroups = [UI.span #. "bar" #+ map element bar | bar <- elCheckboxes]
-    
-    elInstrument <- UI.div #. "instrument"
-        #+ (element elAudio : UI.string name : elGroups)
-    
-    return (beats, elInstrument)
-
diff --git a/src/Foreign/Coupon.hs b/src/Foreign/Coupon.hs
new file mode 100644
--- /dev/null
+++ b/src/Foreign/Coupon.hs
@@ -0,0 +1,181 @@
+{-# LANGUAGE RecordWildCards, CPP #-}
+{-# LANGUAGE MagicHash, UnboxedTuples #-}
+module Foreign.Coupon (
+    -- * Synopsis
+    -- | References to remote objects.
+    -- Offers unique tokens ('Coupon') for communication.
+    -- Supports garbage collection and finalizers.
+    
+    -- * Documentation
+    Coupon,
+    PrizeBooth, newPrizeBooth, lookup,
+    
+    Item, newItem, withItem,
+    addFinalizer, destroy, addReachable, clearReachable,
+    ) where
+
+import Prelude hiding (lookup)
+import Control.Concurrent
+import Control.Monad
+import Control.Exception (evaluate)
+
+import qualified Data.ByteString.Char8 as BS
+import Data.Functor
+import Data.IORef
+import qualified Data.Map as Map
+
+import System.Mem.Weak hiding (addFinalizer)
+import qualified System.Mem.Weak as Weak
+
+import qualified GHC.Base  as GHC
+import qualified GHC.Weak  as GHC
+import qualified GHC.IORef as GHC
+import qualified GHC.STRef as GHC
+
+mkWeakIORefValue :: IORef a -> value -> IO () -> IO (Weak value)
+mkWeakIORefValue r@(GHC.IORef (GHC.STRef r#)) v f = GHC.IO $ \s ->
+  case GHC.mkWeak# r# v f s of (# s1, w #) -> (# s1, GHC.Weak w #)
+
+#if CABAL
+#if MIN_VERSION_base(4,6,0)
+#else
+atomicModifyIORef' = atomicModifyIORef
+#endif
+#endif
+
+debug m = m
+-- debug m = return ()
+
+type Map = Map.Map
+
+{-----------------------------------------------------------------------------
+    Types
+------------------------------------------------------------------------------}
+-- | Coupons can be used as a proxy for 'Item'.
+--
+-- The important point is that coupons can be serialized and sent
+-- over a remote connection.
+--
+-- Coupons are in bijection with items:
+-- Different coupons will yield different items while
+-- the same item will always be associated to the same coupon.
+type Coupon = BS.ByteString
+
+-- | Items represent foreign objects.
+-- The intended use case is that these objects do not live in RAM,
+-- but are only accessible via a remote connection.
+-- 
+-- The foreign object can be accessed by means of the item data of type @a@.
+type Item a = IORef (ItemData a)
+
+data ItemData a = ItemData
+    { self     :: Weak (Item a)
+    , coupon   :: Coupon
+    , value    :: a
+    , children :: IORef [Weak (Item a)]
+    }
+
+
+-- | Remote boothes are a mapping from 'Coupon' to 'Item'.
+--
+-- Prize boothes are neutral concerning garbage collection,
+-- they do not keep items alive.
+-- Moreover, items will be deleted from the booth when they are garbage collected.
+data PrizeBooth a = PrizeBooth
+    { bCoupons :: MVar (Map Coupon (Weak (Item a)))
+    , bCounter :: MVar [Integer]
+    }
+
+{-----------------------------------------------------------------------------
+    Booth and Coupons
+------------------------------------------------------------------------------}
+-- | Create a new prize booth for creating items and trading coupons.
+newPrizeBooth :: IO (PrizeBooth a)
+newPrizeBooth = do
+    bCounter <- newMVar [0..]
+    bCoupons <- newMVar Map.empty
+    return $ PrizeBooth {..}
+
+-- | Take a coupon to the prize booth and maybe you'll get an item for it.
+lookup :: Coupon -> PrizeBooth a -> IO (Maybe (Item a))
+lookup coupon PrizeBooth{..} = do
+    w <- Map.lookup coupon <$> readMVar bCoupons
+    maybe (return Nothing) deRefWeak w
+
+-- | Create a new item, which can be exchanged for a coupon
+-- at an associated prize booth.
+--
+-- The item can become unreachable,
+-- at which point it will be garbage collected,
+-- the finalizers will be run and its
+-- coupon ceases to be valid.
+newItem :: PrizeBooth a -> a -> IO (Item a)
+newItem PrizeBooth{..} value = do
+    coupon   <- BS.pack . show <$> modifyMVar bCounter (\(n:ns) -> return (ns,n))
+    children <- newIORef []
+    let self = undefined
+    item     <- newIORef ItemData{..}
+    
+    let finalize = modifyMVar bCoupons $ \m -> return (Map.delete coupon m, ())
+    w <- mkWeakIORef item finalize
+    modifyMVar bCoupons $ \m -> return (Map.insert coupon w m, ())
+    atomicModifyIORef' item $ \itemdata -> (itemdata { self = w }, ())
+    return item
+
+{-----------------------------------------------------------------------------
+    Items
+------------------------------------------------------------------------------}
+-- | Perform an action with the item.
+-- 
+-- While the action is being performed, it is ensured that the item
+-- will not be garbage collected
+-- and its coupon can be succesfully redeemed at the prize booth.
+withItem :: Item a -> (Coupon -> a -> IO b) -> IO b
+withItem item f = do
+    ItemData{..} <- readIORef item
+    b <- f coupon value
+    touchItem item
+    return b
+
+-- | Make Sure that the item in question is alive
+-- at the given place in the sequence of IO actions.
+touchItem :: Item a -> IO ()
+touchItem item = item `seq` return ()
+
+-- | Destroy an item and run all finalizers for it.
+-- Coupons for this item can no longer be redeemed.
+destroy :: Item a -> IO ()
+destroy item = finalize =<< self <$> readIORef item
+
+-- | Add a finalizer that is run when the item is garbage collected.
+--
+-- The coupon cannot be redeemed anymore while the finalizer runs.
+addFinalizer :: Item a -> IO () -> IO ()
+addFinalizer item = void . mkWeakIORef item
+
+-- | When dealing with several foreign objects,
+-- it is useful to model dependencies between them.
+--
+-- After this operation, the second 'Item' will be reachable
+-- whenever the first one is reachable.
+-- For instance, you should call this function when the second foreign object
+-- is actually a subobject of the first one.
+--
+-- Note: It is possible to model dependencies in the @parent@ data,
+-- but the 'addReachable' method is preferrable,
+-- as it allows all child object to be garbage collected at once.
+addReachable :: Item a -> Item a -> IO ()
+addReachable parent child = do
+    w   <- mkWeakIORefValue parent child $ return ()
+    ref <- children <$> readIORef parent
+    atomicModifyIORef' ref $ \ws -> (w:ws, ())
+
+-- | Clear all dependencies.
+-- 
+-- Reachability of this 'Item' no longer implies reachability
+-- of other items, as formerly implied by calls to 'addReachable'.
+clearReachable :: Item a -> IO ()
+clearReachable item = do
+    ref <- children <$> readIORef item
+    xs  <- atomicModifyIORef' ref $ \xs -> ([], xs)
+    mapM_ finalize xs
diff --git a/src/Graphics/UI/Threepenny.hs b/src/Graphics/UI/Threepenny.hs
--- a/src/Graphics/UI/Threepenny.hs
+++ b/src/Graphics/UI/Threepenny.hs
@@ -14,6 +14,7 @@
     module Graphics.UI.Threepenny.Events,
     module Graphics.UI.Threepenny.JQuery,
     module Graphics.UI.Threepenny.Timer,
+    module Graphics.UI.Threepenny.Widgets,
     ) where
 
 import Graphics.UI.Threepenny.Attributes
@@ -24,6 +25,7 @@
 import Graphics.UI.Threepenny.Events
 import Graphics.UI.Threepenny.JQuery
 import Graphics.UI.Threepenny.Timer
+import Graphics.UI.Threepenny.Widgets
 
 {- $intro
 
@@ -68,7 +70,7 @@
 the following function will be executed to start the GUI interaction.
 It builds the initial HTML page.
 
-> setup :: Window -> IO ()
+> setup :: Window -> UI ()
 > setup window = do
 
 First, set the title of the HTML document
@@ -99,7 +101,7 @@
 That's it for a first example!
 
 The libary comes with a
-<https://github.com/HeinrichApfelmus/threepenny-gui/tree/master/src plethora of additional example code>.
+<https://github.com/HeinrichApfelmus/threepenny-gui#examples plethora of additional example code>.
 
 
 -}
diff --git a/src/Graphics/UI/Threepenny/Canvas.hs b/src/Graphics/UI/Threepenny/Canvas.hs
--- a/src/Graphics/UI/Threepenny/Canvas.hs
+++ b/src/Graphics/UI/Threepenny/Canvas.hs
@@ -8,8 +8,6 @@
     ) where
 
 import Graphics.UI.Threepenny.Core
-import qualified Graphics.UI.Threepenny.Internal.Core as Core
-import qualified Graphics.UI.Threepenny.Internal.Types as Core
 
 {-----------------------------------------------------------------------------
     Canvas
@@ -19,16 +17,12 @@
 type Vector = (Int,Int)
 
 -- | Draw the image of an image element onto the canvas at a specified position.
-drawImage :: Element -> Vector -> Canvas -> IO ()
-drawImage eimage (x,y) = updateElement $ \(Core.Element canvas window) -> do
-    image <- manifestElement window eimage
-    runFunction window $
-        ffi "%1.getContext('2d').drawImage(%2,%3,%4)" canvas image x y
+drawImage :: Element -> Vector -> Canvas -> UI ()
+drawImage image (x,y) canvas =
+    runFunction $ ffi "%1.getContext('2d').drawImage(%2,%3,%4)" canvas image x y
 
 -- | Clear the canvas
-clearCanvas :: Canvas -> IO ()
-clearCanvas = updateElement $ \(Core.Element canvas window) -> do
-    runFunction window $
-        ffi "%1.getContext('2d').clear()" canvas
+clearCanvas :: Canvas -> UI ()
+clearCanvas = runFunction . ffi "%1.getContext('2d').clear()"
 
 
diff --git a/src/Graphics/UI/Threepenny/Core.hs b/src/Graphics/UI/Threepenny/Core.hs
--- a/src/Graphics/UI/Threepenny/Core.hs
+++ b/src/Graphics/UI/Threepenny/Core.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE DeriveDataTypeable, RecordWildCards #-}
+{-# LANGUAGE RecursiveDo #-}
 module Graphics.UI.Threepenny.Core (
     -- * Synopsis
     -- | Core functionality of the Threepenny GUI library.
@@ -8,6 +9,12 @@
     Config(..), defaultConfig, startGUI,
     loadFile, loadDirectory,
     
+    -- * UI monad
+    -- $ui
+    UI, runUI, askWindow, liftIOLater,
+    module Control.Monad.IO.Class,
+    module Control.Monad.Fix,
+    
     -- * Browser Window
     Window, title, cookies, getRequestLocation,
     
@@ -17,9 +24,7 @@
         getHead, getBody,
         children, text, html, attr, style, value,
     getValuesList,
-    getElementsByTagName, getElementByTagName, 
-    getElementsById, getElementById,
-    getElementsByClassName,
+    getElementsByTagName, getElementById, getElementsByClassName,
     
     -- * Layout
     -- | Combinators for quickly creating layouts.
@@ -28,23 +33,26 @@
     
     -- * Events
     -- | For a list of predefined events, see "Graphics.UI.Threepenny.Events".
-    EventData(..), domEvent, on, disconnect,
+    EventData(..), domEvent, disconnect, on, onEvent, onChanges,
     module Reactive.Threepenny,
     
     -- * Attributes
     -- | For a list of predefined attributes, see "Graphics.UI.Threepenny.Attributes".
-    (#), (#.), element,
+    (#), (#.),
     Attr, WriteAttr, ReadAttr, ReadWriteAttr(..),
     set, sink, get, mkReadWriteAttr, mkWriteAttr, mkReadAttr,
     
+    -- * Widgets
+    Widget(..), element, widget,
+    
     -- * JavaScript FFI
     -- | Direct interface to JavaScript in the browser window.
-    debug, clear,
+    debug,
     ToJS, FFI, ffi, JSFunction, runFunction, callFunction,
     callDeferredFunction, atomic,
     
     -- * Internal and oddball functions
-    updateElement, manifestElement, fromProp,
+    fromProp, toElement,
     audioPlay, audioStop,
     
     ) where
@@ -55,22 +63,32 @@
 import Data.Maybe (listToMaybe)
 import Data.Functor
 import Data.String (fromString)
+
 import Control.Concurrent.MVar
 import Control.Monad
+import Control.Monad.Fix
 import Control.Monad.IO.Class
+import qualified Control.Monad.Trans.RWS.Lazy as Monad
+
 import Network.URI
 import Text.JSON
-import Reactive.Threepenny
 
-import qualified Graphics.UI.Threepenny.Internal.Core  as Core
-import Graphics.UI.Threepenny.Internal.Core
-    (getRequestLocation,
-     ToJS, FFI, ffi, JSFunction,
-     debug, clear, callFunction, runFunction, callDeferredFunction, atomic, )
-import qualified Graphics.UI.Threepenny.Internal.Types as Core
-import Graphics.UI.Threepenny.Internal.Types
-    (Window, Config, defaultConfig, EventData, Session(..))
+import           Reactive.Threepenny hiding (onChange)
+import qualified Reactive.Threepenny as Reactive
 
+import qualified Graphics.UI.Threepenny.Internal.Driver  as Core
+import           Graphics.UI.Threepenny.Internal.Driver
+    ( getRequestLocation
+    , callDeferredFunction, atomic, )
+import           Graphics.UI.Threepenny.Internal.FFI
+import           Graphics.UI.Threepenny.Internal.Types   as Core
+    ( Window, Config, defaultConfig, Events, EventData
+    , ElementData(..), withElementData,)
+
+
+import Graphics.UI.Threepenny.Internal.Types as Core
+    (unprotectedGetElementId, withElementData, ElementData(..))
+
 {-----------------------------------------------------------------------------
     Server
 ------------------------------------------------------------------------------}
@@ -93,272 +111,265 @@
 -- | Start server for GUI sessions.
 startGUI
     :: Config               -- ^ Server configuration.
-    -> (Window -> IO ())    -- ^ Action to run whenever a client browser connects.
+    -> (Window -> UI ())    -- ^ Action to run whenever a client browser connects.
     -> IO ()
-startGUI config handler = Core.serve config handler
+startGUI config handler = Core.serve config (\w -> runUI w $ handler w)
 
 
 -- | Make a local file available as a relative URI.
 loadFile
-    :: Window     -- ^ Browser window
-    -> String     -- ^ MIME type
+    :: String     -- ^ MIME type
     -> FilePath   -- ^ Local path to the file
-    -> IO String  -- ^ Generated URI
-loadFile w mime path = Core.loadFile w (fromString mime) path
+    -> UI String  -- ^ Generated URI
+loadFile mime path = askWindow >>= \w -> liftIO $
+    Core.loadFile w (fromString mime) path
 
 -- | Make a local directory available as a relative URI.
-loadDirectory :: Window -> FilePath -> IO String
-loadDirectory = Core.loadDirectory
+loadDirectory :: FilePath -> UI String
+loadDirectory path = askWindow >>= \w -> liftIO $
+    Core.loadDirectory w path
 
+
 {-----------------------------------------------------------------------------
+    UI monad
+------------------------------------------------------------------------------}
+{- |
+
+User interface elements are created and manipulated in the 'UI' monad.
+
+This monad is essentially just a thin wrapper around the familiar 'IO' monad.
+Use the 'liftIO' function to access 'IO' operations like reading
+and writing from files.
+
+There are several subtle reasons why Threepenny
+uses a custom 'UI' monad instead of the standard 'IO' monad:
+
+* More convenience when calling JavaScript.
+The monad keeps track of a browser 'Window' context
+in which JavaScript function calls are executed.
+
+* Recursion for functional reactive programming.
+
+-}
+newtype UI a = UI { unUI :: Monad.RWST Window [IO ()] () IO a }
+    deriving (Typeable)
+
+instance Functor UI where
+    fmap f = UI . fmap f . unUI
+
+instance Monad UI where
+    return  = UI . return
+    m >>= k = UI $ unUI m >>= unUI . k
+
+instance MonadIO UI where
+    liftIO = UI . liftIO
+
+instance MonadFix UI where
+    mfix f = UI $ mfix (unUI . f)  
+
+-- | Execute an 'UI' action in a particular browser window.
+-- Also runs all scheduled 'IO' action.
+runUI :: Window -> UI a -> IO a
+runUI window m = do
+    (a, _, actions) <- Monad.runRWST (unUI m) window ()
+    sequence_ actions
+    return a
+
+-- | Retrieve current 'Window' context in the 'UI' monad.
+askWindow :: UI Window
+askWindow = UI Monad.ask
+
+-- | Schedule an 'IO' action to be run later.
+liftIOLater :: IO () -> UI ()
+liftIOLater x = UI $ Monad.tell [x]
+
+{-----------------------------------------------------------------------------
     Browser window
 ------------------------------------------------------------------------------}
 -- | Title of the client window.
 title :: WriteAttr Window String
-title = mkWriteAttr Core.setTitle
+title = mkWriteAttr $ \s _ ->
+    runFunction $ ffi "document.title = %1;" s
 
 -- | Cookies on the client.
 cookies :: ReadAttr Window [(String,String)]
-cookies = mkReadAttr Core.getRequestCookies
+cookies = mkReadAttr (liftIO . Core.getRequestCookies)
 
 {-----------------------------------------------------------------------------
     Elements
 ------------------------------------------------------------------------------}
-type Value = String
-
--- | Reference to an element in the DOM of the client window.
-data Element = Element Core.ElementEvents (MVar Elem) deriving (Typeable)
--- Element events mvar
---      events = Events associated to this element
---      mvar   = Current state of the MVar
-data    Elem
-    = Alive Core.Element                       -- element exists in a window
-    | Limbo Value (Window -> IO Core.Element)  -- still needs to be created
-
--- Turn a live reference into an 'Element'.
--- Note that multiple MVars may now point to the same live reference,
--- but this is ok since live references never change.
-fromAlive :: Core.Element -> IO Element
-fromAlive e@(Core.Element elid Session{..}) = do
-    Just events <- Map.lookup elid <$> readMVar sElementEvents
-    Element events <$> newMVar (Alive e)
-
--- Update an element that may be in Limbo.
-updateElement :: (Core.Element -> IO ()) -> Element -> IO ()
-updateElement f (Element _ me) = do
-    e <- takeMVar me
-    case e of
-        Alive e -> do   -- update immediately
-            f e
-            putMVar me $ Alive e
-        Limbo value create ->      -- update on creation
-            putMVar me $ Limbo value $ \w -> create w >>= \e -> f e >> return e
-
--- Given a browser window, make sure that the element exists there.
--- TODO: 1. Throw exception if the element exists in another window.
---       2. Don't throw exception, but move the element across windows.
-manifestElement :: Window -> Element -> IO Core.Element
-manifestElement w (Element events me) = do
-        e1 <- takeMVar me
-        e2 <- case e1 of
-            Alive e        -> return e
-            Limbo v create -> do
-                e2 <- create w
-                Core.setAttr "value" v e2
-                rememberEvents events e2    -- save events in session data
-                return e2
-        putMVar me $ Alive e2
-        return e2
-    
-    where
-    rememberEvents events (Core.Element elid Session{..}) =
-        modifyMVar_ sElementEvents $ return . Map.insert elid events
+data Element = Element { eEvents :: Core.Events, toElement :: Core.Element }
+    deriving (Typeable)
 
+fromElement :: Core.Element -> IO Element
+fromElement e = do
+    events <- Core.withElementData e $ \_ x -> return $ elEvents x 
+    return $ Element events e
 
--- Append a child element to a parent element. Non-blocking.
-appendTo
-    :: Element   -- ^ Parent.
-    -> Element   -- ^ Child.
-    -> IO ()
-appendTo parent child = do
-    flip updateElement parent $ \x -> do
-        y <- manifestElement (Core.getWindow x) child
-        Core.appendElementTo x y
+instance ToJS Element where
+    render = render . toElement
 
 -- | Make a new DOM element.
 mkElement
     :: String           -- ^ Tag name
-    -> IO Element
-mkElement tag = do
-    -- create element in Limbo
-    ref <- newMVar (Limbo "" $ \w -> Core.newElement w tag)
+    -> UI Element
+mkElement tag = mdo
     -- create events and initialize them when element becomes Alive
-    let
-        initializeEvent (name,_,handler) = 
-            flip updateElement (Element undefined ref) $ \e -> do
-                Core.bind name e handler
-    events  <- newEventsNamed initializeEvent
-    return $ Element events ref
+    let initializeEvent (name,_,handler) = Core.bind name el handler
+    events  <- liftIO $ newEventsNamed initializeEvent
+    
+    window  <- askWindow
+    el      <- liftIO $ Core.newElement window tag events
+    return $ Element events el
 
 -- | Retrieve the browser 'Window' in which the element resides.
--- 
--- Note that elements do not reside in any browser window when they are first created.
--- To move the element to a particular browser window,
--- you have to append it to a parent, for instance with the `(#+)` operator.
---
--- WARNING: The ability to move elements from one browser window to another
--- is currently not implemented yet.
-getWindow :: Element -> IO (Maybe Window)
-getWindow (Element _ ref) = do
-    e1 <- readMVar ref
-    return $ case e1 of
-        Alive e   -> Just $ Core.getWindow e
-        Limbo _ _ -> Nothing
+getWindow :: Element -> IO Window
+getWindow e = Core.getWindow (toElement e)
 
 -- | Delete the given element.
-delete :: Element -> IO ()
-delete = updateElement (Core.delete)
+delete :: Element -> UI ()
+delete = liftIO . Core.delete . toElement
 
 -- | Append DOM elements as children to a given element.
-(#+) :: IO Element -> [IO Element] -> IO Element
+(#+) :: UI Element -> [UI Element] -> UI Element
 (#+) mx mys = do
     x  <- mx
     ys <- sequence mys
-    mapM_ (appendTo x) ys
+    liftIO $ mapM_ (Core.appendElementTo (toElement x) . toElement) ys
     return x
 
 -- | Child elements of a given element.
 children :: WriteAttr Element [Element]
 children = mkWriteAttr set
     where
-    set xs x = do
-        updateElement Core.emptyEl x
-        mapM_ (appendTo x) xs
+    set xs x = liftIO $ do
+        Core.emptyEl $ toElement x
+        mapM_ (Core.appendElementTo (toElement x) . toElement) xs
 
 -- | Child elements of a given element as a HTML string.
 html :: WriteAttr Element String
-html = mkWriteAttr (updateElement . Core.setHtml)
+html = mkWriteAttr $ \s el ->
+    runFunction $ ffi "$(%1).html(%2)" el s
 
 -- | HTML attributes of an element.
 attr :: String -> WriteAttr Element String
-attr name = mkWriteAttr (updateElement . Core.setAttr name)
+attr name = mkWriteAttr $ \s el ->
+    runFunction $ ffi "$(%1).attr(%2,%3)" el name s
 
 -- | Set CSS style of an Element
 style :: WriteAttr Element [(String,String)]
-style = mkWriteAttr (updateElement . Core.setStyle)
+style = mkWriteAttr $ \xs el -> forM_ xs $ \(name,val) -> 
+    runFunction $ ffi "%1.style[%2] = %3" el name val
 
 -- | Value attribute of an element.
 -- Particularly relevant for control widgets like 'input'.
 value :: Attr Element String
 value = mkReadWriteAttr get set
     where
-    get   (Element _ ref) = getValue =<< readMVar ref
-    set v (Element _ ref) = updateMVar (setValue v) ref
-    
-    getValue (Limbo v _) = return v
-    getValue (Alive e  ) = Core.getValue e
-    
-    setValue v (Limbo _ f) = return $ Limbo v f
-    setValue v (Alive e  ) = Core.setAttr "value" v e >> return (Alive e)
-    
-    updateMVar f ref = do
-        x <- takeMVar ref
-        y <- f x
-        putMVar ref y
+    get   el = callFunction $ ffi "$(%1).val()" el
+    set v el = runFunction  $ ffi "$(%1).val(%2)" el v
 
 -- | Get values from inputs. Blocks. This is faster than many 'getValue' invocations.
 getValuesList
     :: [Element]   -- ^ A list of elements to get the values of.
-    -> IO [String] -- ^ The list of plain text values.
+    -> UI [String] -- ^ The list of plain text values.
 getValuesList = mapM (get value)
     -- TODO: improve this to use Core.getValuesList
 
 -- | Text content of an element.
 text :: WriteAttr Element String
-text = mkWriteAttr (updateElement . Core.setText)
+text = mkWriteAttr $ \s el ->
+    runFunction $ ffi "$(%1).text(%2)" el s
 
 -- | Make a @span@ element with a given text content.
-string :: String -> IO Element
+string :: String -> UI Element
 string s = mkElement "span" # set text s
 
 
 -- | Get the head of the page.
-getHead :: Window -> IO Element
-getHead = fromAlive <=< Core.getHead
+getHead :: Window -> UI Element
+getHead w = liftIO $ fromElement =<< Core.getHead w
 
 -- | Get the body of the page.
-getBody :: Window -> IO Element
-getBody = fromAlive <=< Core.getBody
-
--- | Get an element by its tag name.  Blocks.
-getElementByTagName
-    :: Window             -- ^ Browser window
-    -> String             -- ^ The tag name.
-    -> IO (Maybe Element) -- ^ An element (if any) with that tag name.
-getElementByTagName window = liftM listToMaybe . getElementsByTagName window
+getBody :: Window -> UI Element
+getBody w = liftIO $ fromElement =<< Core.getBody w
 
 -- | Get all elements of the given tag name.  Blocks.
 getElementsByTagName
     :: Window        -- ^ Browser window
     -> String        -- ^ The tag name.
-    -> IO [Element]  -- ^ All elements with that tag name.
-getElementsByTagName window name =
-    mapM fromAlive =<< Core.getElementsByTagName window name
+    -> UI [Element]  -- ^ All elements with that tag name.
+getElementsByTagName window name = liftIO $
+    mapM fromElement =<< Core.getElementsByTagName window name
 
 -- | Get an element by a particular ID.  Blocks.
 getElementById
     :: Window              -- ^ Browser window
     -> String              -- ^ The ID string.
-    -> IO (Maybe Element)  -- ^ Element (if any) with given ID.
-getElementById window id = listToMaybe `fmap` getElementsById window [id]
-
--- | Get a list of elements by particular IDs.  Blocks.
-getElementsById
-    :: Window        -- ^ Browser window
-    -> [String]      -- ^ The ID string.
-    -> IO [Element]  -- ^ Elements with given ID.
-getElementsById window name =
-    mapM fromAlive =<< Core.getElementsById window name
+    -> UI (Maybe Element)  -- ^ Element (if any) with given ID.
+getElementById window id = liftIO $
+    fmap listToMaybe $ mapM fromElement =<< Core.getElementsById window [id]
 
 -- | Get a list of elements by particular class.  Blocks.
 getElementsByClassName
     :: Window        -- ^ Browser window
     -> String        -- ^ The class string.
-    -> IO [Element]  -- ^ Elements with given class.
-getElementsByClassName window cls =
-    mapM fromAlive =<< Core.getElementsByClassName window cls
+    -> UI [Element]  -- ^ Elements with given class.
+getElementsByClassName window cls = liftIO $
+    mapM fromElement =<< Core.getElementsByClassName window cls
 
+
 {-----------------------------------------------------------------------------
+    FFI
+------------------------------------------------------------------------------}
+-- | Run the given JavaScript function and carry on. Doesn't block.
+--
+-- The client window uses JavaScript's @eval()@ function to run the code.
+runFunction :: JSFunction () -> UI ()
+runFunction fun = do
+    window <- askWindow
+    liftIO $ Core.runFunction window fun 
+
+-- | Run the given JavaScript function and wait for results. Blocks.
+--
+-- The client window uses JavaScript's @eval()@ function to run the code.
+callFunction :: JSFunction a -> UI a
+callFunction fun = do
+    window <- askWindow
+    liftIO $ Core.callFunction window fun
+
+
+{-----------------------------------------------------------------------------
     Oddball
 ------------------------------------------------------------------------------}
+-- | Print a message on the client console if the client has debugging enabled.
+debug :: String -> UI ()
+debug s = askWindow >>= \w -> liftIO $ Core.debug w s
+
 -- | Invoke the JavaScript expression @audioElement.play();@.
-audioPlay = updateElement $ \el -> Core.runFunction (Core.getWindow el) $
-    ffi "%1.play()" el
+audioPlay :: Element -> UI ()
+audioPlay el = runFunction $ ffi "%1.play()" el
 
 -- | Invoke the JavaScript expression @audioElement.stop();@.
-audioStop = updateElement $ \el -> Core.runFunction (Core.getWindow el) $
-    ffi "prim_audio_stop(%1)" el
+audioStop :: Element -> UI ()
+audioStop el = runFunction $ ffi "prim_audio_stop(%1)" el
 
 -- Turn a jQuery property @.prop()@ into an attribute.
 fromProp :: String -> (JSValue -> a) -> (a -> JSValue) -> Attr Element a
 fromProp name from to = mkReadWriteAttr get set
     where
-    set x = updateElement (Core.setProp name $ to x)
-    get (Element _ ref) = do
-        me <- readMVar ref
-        case me of
-            Limbo _ _ -> error "'checked' attribute: element must be in a browser window"
-            Alive e   -> from <$> Core.getProp name e
+    set v el = runFunction $ ffi "$(%1).prop(%2,%3)" el name (to v)
+    get   el = fmap from $ callFunction $ ffi "$(%1).prop(%2)" el name
 
 {-----------------------------------------------------------------------------
     Layout
 ------------------------------------------------------------------------------}
 -- | Align given elements in a row. Special case of 'grid'.
-row :: [IO Element] -> IO Element
+row :: [UI Element] -> UI Element
 row xs = grid [xs]
 
 -- | Align given elements in a column. Special case of 'grid'.
-column :: [IO Element] -> IO Element
+column :: [UI Element] -> UI Element
 column = grid . map (:[])
 
 -- | Align given elements in a rectangular grid.
@@ -380,7 +391,7 @@
 -- You can customatize the actual layout by assigning an @id@ to the element
 -- and changing the @.table@, @.table-row@ and @table-column@
 -- classes in a custom CSS file.
-grid    :: [[IO Element]] -> IO Element
+grid    :: [[UI Element]] -> UI Element
 grid mrows = do
         rows0 <- mapM (sequence) mrows
     
@@ -407,21 +418,6 @@
     -> Event EventData
 domEvent name (Element events _) = events name
 
-{-   
-    ref <- newIORef $ return ()
-    let
-        -- register handler and remember unregister function
-        register' = flip updateElement element $ \e -> do
-            unregister <- register (Core.bind name e) handler
-            writeIORef ref unregister
-        
-        -- update element to unregister the event handler
-        unregister' = flip updateElement element $ \_ -> do
-            join $ readIORef ref
-    
-    register'
-    return unregister'
--}
 
 -- | Event that occurs whenever the client has disconnected,
 -- be it by closing the browser window or by exception.
@@ -436,10 +432,26 @@
 -- Example usage.
 --
 -- > on click element $ \_ -> ...
-on :: (element -> Event a) -> element -> (a -> IO void) -> IO ()
-on f x h = register (f x) (void . h) >> return ()
+on :: (element -> Event a) -> element -> (a -> UI void) -> UI ()
+on f x = onEvent (f x)
 
+-- | Register an 'UI' action to be executed whenever the 'Event' happens.
+-- 
+-- FIXME: Should be unified with 'on'?
+onEvent :: Event a -> (a -> UI void) -> UI ()
+onEvent e h = do
+    window <- askWindow
+    liftIO $ register e (void . runUI window . h)
+    return ()
 
+-- | Execute a 'UI' action whenever a 'Behavior' changes.
+-- Use sparingly, it is recommended that you use 'sink' instead.
+onChanges :: Behavior a -> (a -> UI void) -> UI ()
+onChanges b f = do
+    window <- askWindow
+    liftIO $ Reactive.onChange b (void . runUI window . f)
+
+
 {-----------------------------------------------------------------------------
     Attributes
 ------------------------------------------------------------------------------}
@@ -460,20 +472,9 @@
 (#) = flip ($)
 
 -- | Convenient combinator for setting the CSS class on element creation.
-(#.) :: IO Element -> String -> IO Element
+(#.) :: UI Element -> String -> UI Element
 (#.) mx s = mx # set (attr "class") s
 
-
--- | Convience synonym for 'return' to make elements work well with 'set'.
---
--- Example usage.
---
--- > e <- mkElement "button"
--- > element e # set text "Ok"
-element :: Element -> IO Element
-element = return
-
-
 -- | Attributes can be 'set' and 'get'.
 type Attr x a = ReadWriteAttr x a a
 
@@ -485,44 +486,71 @@
 
 -- | Generalized attribute with different types for getting and setting.
 data ReadWriteAttr x i o = ReadWriteAttr
-    { get' :: x -> IO o
-    , set' :: i -> x -> IO ()
+    { get' :: x -> UI o
+    , set' :: i -> x -> UI ()
     }
 
--- | Set value of an attribute in the 'IO' monad.
+-- | Set value of an attribute in the 'UI' monad.
 -- Best used in conjunction with '#'.
-set :: MonadIO m => ReadWriteAttr x i o -> i -> m x -> m x
-set attr i mx = do { x <- mx; liftIO (set' attr i x); return x; }
+set :: ReadWriteAttr x i o -> i -> UI x -> UI x
+set attr i mx = do { x <- mx; set' attr i x; return x; }
 
 -- | Set the value of an attribute to a 'Behavior', that is a time-varying value.
 --
 -- Note: For reasons of efficiency, the attribute is only
 -- updated when the value changes.
-sink :: ReadWriteAttr x i o -> Behavior i -> IO x -> IO x
+sink :: ReadWriteAttr x i o -> Behavior i -> UI x -> UI x
 sink attr bi mx = do
     x <- mx
-    do
+    window <- askWindow
+    liftIOLater $ do
         i <- currentValue bi
-        set' attr i x
-        onChange bi $ \i -> set' attr i x  
+        runUI window $ set' attr i x
+        Reactive.onChange bi  $ \i -> runUI window $ set' attr i x  
     return x
 
 -- | Get attribute value.
-get :: ReadWriteAttr x i o -> x -> IO o
-get = get'
+get :: ReadWriteAttr x i o -> x -> UI o
+get attr = get' attr
 
 -- | Build an attribute from a getter and a setter.
 mkReadWriteAttr
-    :: (x -> IO o)          -- ^ Getter.
-    -> (i -> x -> IO ())    -- ^ Setter.
+    :: (x -> UI o)          -- ^ Getter.
+    -> (i -> x -> UI ())    -- ^ Setter.
     -> ReadWriteAttr x i o
 mkReadWriteAttr get set = ReadWriteAttr { get' = get, set' = set }
 
 -- | Build attribute from a getter.
-mkReadAttr :: (x -> IO o) -> ReadAttr x o
+mkReadAttr :: (x -> UI o) -> ReadAttr x o
 mkReadAttr get = mkReadWriteAttr get (\_ _ -> return ())
 
 -- | Build attribute from a setter.
-mkWriteAttr :: (i -> x -> IO ()) -> WriteAttr x i
+mkWriteAttr :: (i -> x -> UI ()) -> WriteAttr x i
 mkWriteAttr set = mkReadWriteAttr (\_ -> return ()) set
+
+
+{-----------------------------------------------------------------------------
+    Widget class
+------------------------------------------------------------------------------}
+-- | Widgets are data types that have a visual representation.
+class Widget w where
+    getElement :: w -> Element
+
+instance Widget Element where
+    getElement = id
+
+
+-- | Convience synonym for 'return' to make elements work well with 'set'.
+-- Also works on 'Widget's.
+--
+-- Example usage.
+--
+-- > e <- mkElement "button"
+-- > element e # set text "Ok"
+element :: MonadIO m => Widget w => w -> m Element
+element = return . getElement
+
+-- | Convience synonym for 'return' to make widgets work well with 'set'.
+widget  :: Widget w => w -> UI w
+widget  = return
 
diff --git a/src/Graphics/UI/Threepenny/Elements.hs b/src/Graphics/UI/Threepenny/Elements.hs
--- a/src/Graphics/UI/Threepenny/Elements.hs
+++ b/src/Graphics/UI/Threepenny/Elements.hs
@@ -38,7 +38,7 @@
 addStyleSheet
     :: Window
     -> FilePath
-    -> IO ()
+    -> UI ()
 addStyleSheet w filename = void $ do
     el <- mkElement "link"
             # set (attr "rel" ) "stylesheet"
@@ -47,7 +47,7 @@
     getHead w #+ [element el]
 
 -- | Make a new @div@ element, synonym for 'div'.
-new :: IO Element
+new :: UI Element
 new = div
 
 {-----------------------------------------------------------------------------
diff --git a/src/Graphics/UI/Threepenny/Events.hs b/src/Graphics/UI/Threepenny/Events.hs
--- a/src/Graphics/UI/Threepenny/Events.hs
+++ b/src/Graphics/UI/Threepenny/Events.hs
@@ -6,7 +6,8 @@
     valueChange, selectionChange, checkedChange,
     
     -- * Standard DOM events
-    click, mousemove, hover, blur, leave,
+    click, mousemove, mousedown, mouseup, hover, leave,
+    focus, blur,
     KeyCode, keyup, keydown,
     ) where
 
@@ -20,16 +21,18 @@
 ------------------------------------------------------------------------------}
 -- | Event that occurs when the /user/ changes the value of the input element.
 valueChange :: Element -> Event String
-valueChange el = unsafeMapIO (const $ get value el) (domEvent "keydown" el)
+valueChange el = unsafeMapUI el (const $ get value el) (domEvent "keydown" el)
 
+unsafeMapUI el f = unsafeMapIO (\a -> getWindow el >>= \w -> runUI w (f a))
+
 -- | Event that occurs when the /user/ changes the selection of a @<select>@ element.
 selectionChange :: Element -> Event (Maybe Int)
-selectionChange el = unsafeMapIO (const $ get selection el) (click el)
+selectionChange el = unsafeMapUI el (const $ get selection el) (click el)
 
 -- | Event that occurs when the /user/ changes the checked status of an input
 -- element of type checkbox.
 checkedChange :: Element -> Event Bool
-checkedChange el = unsafeMapIO (const $ get checked el) (click el)
+checkedChange el = unsafeMapUI el (const $ get checked el) (click el)
 
 {-----------------------------------------------------------------------------
     DOM Events
@@ -38,25 +41,41 @@
 click :: Element -> Event ()
 click = silence . domEvent "click"
 
--- | Mouse hovering over an element.
+-- | Mouse enters an element.
 hover :: Element -> Event ()
 hover = silence . domEvent "mouseenter"
 
 -- | Event that periodically occurs while the mouse is moving over an element.
 --
 -- The event value represents the mouse coordinates
--- relative to the upper left corner of the entire page.
+-- relative to the upper left corner of the element.
 --
 -- Note: The @<body>@ element responds to mouse move events,
 -- but only in the area occupied by actual content,
 -- not the whole browser window.
 mousemove :: Element -> Event (Int,Int)
-mousemove = fmap readPair . domEvent "mousemove"
-    where readPair (EventData (Just x:Just y:_)) = (read x, read y)
+mousemove = fmap readCoordinates . domEvent "mousemove"
 
+readCoordinates :: EventData -> (Int,Int)
+readCoordinates (EventData (Just x:Just y:_)) = (read x, read y)
+
+-- | Mouse down event.
+-- The mouse coordinates are relative to the element. 
+mousedown :: Element -> Event (Int,Int)
+mousedown = fmap readCoordinates . domEvent "mousedown"
+
+-- | Mouse up event.
+-- The mouse coordinates are relative to the element. 
+mouseup :: Element -> Event (Int,Int)
+mouseup = fmap readCoordinates . domEvent "mouseup"
+
 -- | Mouse leaving an element.
 leave :: Element -> Event ()
 leave = silence . domEvent "mouseleave"
+
+-- | Element receives focus.
+focus :: Element -> Event ()
+focus = silence . domEvent "focus"
 
 -- | Element loses focus.
 blur :: Element -> Event ()
diff --git a/src/Graphics/UI/Threepenny/Internal/Core.hs b/src/Graphics/UI/Threepenny/Internal/Core.hs
deleted file mode 100644
--- a/src/Graphics/UI/Threepenny/Internal/Core.hs
+++ /dev/null
@@ -1,732 +0,0 @@
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE OverloadedStrings, PackageImports #-}
-{-# OPTIONS -fno-warn-name-shadowing #-}
-
-module Graphics.UI.Threepenny.Internal.Core
-  (
-  -- * Synopsis
-  -- | The main internal functionality.
-      
-  -- * Server running
-   serve
-  ,loadFile
-  ,loadDirectory
-  
-  -- * Event handling
-  -- $eventhandling
-  ,bind
-  ,disconnect
-  ,module Reactive.Threepenny
-  
-  -- * Setting attributes
-  -- $settingattributes
-  ,setStyle
-  ,setAttr
-  ,setProp
-  ,setText
-  ,setHtml
-  ,setTitle
-  ,emptyEl
-  ,delete
-  
-  -- * Manipulating tree structure
-  -- $treestructure
-  ,newElement
-  ,appendElementTo
-  
-  -- * Querying
-  -- $querying
-  ,getHead
-  ,getBody
-  ,getElementsByTagName
-  ,getElementsById
-  ,getElementsByClassName
-  ,getWindow
-  ,getProp
-  ,getValue
-  ,getValuesList
-  ,readValue
-  ,readValuesList
-  ,getRequestCookies
-  ,getRequestLocation
-  
-  -- * Utilities
-  ,debug
-  ,clear
-  ,callDeferredFunction
-  ,atomic
-
-  -- * JavaScript FFI
-  ,ToJS, FFI, ffi, JSFunction
-  ,runFunction, callFunction
-  
-  -- * Types
-  ,Window
-  ,Element
-  ,Config(..)
-  ,EventData(..)
-  ) where
-
-
-
-import           Graphics.UI.Threepenny.Internal.Types     as Threepenny
-import           Graphics.UI.Threepenny.Internal.Resources
-
-import           Control.Applicative
-import           Control.Concurrent
-import           Control.Concurrent.Chan.Extra
-import           Control.Concurrent.Delay
-import qualified Control.Exception
-import           Reactive.Threepenny
-import           Control.Monad
-import           Control.Monad.IO.Class
-import qualified "MonadCatchIO-transformers" Control.Monad.CatchIO as E
-import           Data.ByteString               (ByteString)
-import           Data.ByteString.UTF8          (toString,fromString)
-import           Data.Map                      (Map)
-import qualified Data.Map                      as M
-import           Data.Maybe
-import           Data.Text                     (Text,pack,unpack)
-import qualified Data.Text                     as Text
-import           Data.Text.Encoding
-import           Data.Time
-import           Network.URI
-import qualified Network.WebSockets            as WS
-import qualified Network.WebSockets.Snap       as WS
-import qualified Data.Attoparsec.Enumerator    as Atto
-import           Prelude                       hiding (init)
-import           Safe
-import           Snap.Core
-import qualified Snap.Http.Server              as Snap
-import           Snap.Util.FileServe
-import           System.FilePath
-import qualified Text.JSON as JSON
-import           Text.JSON.Generic
-
-
-{-----------------------------------------------------------------------------
-    Server and and session management
-------------------------------------------------------------------------------}
-newServerState :: IO ServerState
-newServerState = ServerState 
-    <$> newMVar M.empty
-    <*> newMVar (0,M.empty)
-    <*> newMVar (0,M.empty)
-
--- | Run a TP server with Snap on the specified port and the given
---   worker action.
-serve :: Config -> (Session -> IO ()) -> IO ()
-serve Config{..} worker = do
-    server <- newServerState
-    _      <- forkIO $ custodian 30 (sSessions server)
-    let config = Snap.setPort tpPort
-               $ Snap.setErrorLog (Snap.ConfigIoLog tpLog)
-               $ Snap.setAccessLog (Snap.ConfigIoLog tpLog)
-               $ Snap.defaultConfig
-    Snap.httpServe config . route $
-        routeResources tpCustomHTML tpStatic server
-        -- ++ routeCommunication worker server
-        ++ routeWebsockets worker server
-
--- | Kill sessions after at least n seconds of disconnectedness.
-custodian :: Integer -> MVar Sessions -> IO ()
-custodian seconds sessions = forever $ do
-  delaySeconds seconds
-  modifyMVar_ sessions $ \sessions -> do
-    killed <- fmap catMaybes $ forM (M.assocs sessions) $ \(key,Session{..}) -> do
-      state <- readMVar sConnectedState
-      case state of
-        Connected -> return Nothing
-        Disconnected time -> do
-          now <- getCurrentTime
-          let dcSeconds = diffUTCTime now time
-          -- session is disconnected for more than  seconds
-          if (dcSeconds > fromIntegral seconds)
-             then do killThread sThreadId
-                     return (Just key)
-             else return Nothing
-    
-    -- remove killed sessions from the map
-    return (M.filterWithKey (\k _ -> not (k `elem` killed)) sessions)
-
--- Run a snap action with the given session.
-withSession :: ServerState -> (Session -> Snap a) -> Snap a
-withSession server cont = do
-    token <- readInput "token"
-    case token of
-        Nothing    -> error $ "Invalid session token format."
-        Just token -> withGivenSession token server cont
-
--- Do something with the session given by its token id.
-withGivenSession :: Integer -> ServerState -> (Session -> Snap a) -> Snap a
-withGivenSession token ServerState{..} cont = do
-    sessions <- liftIO $ withMVar sSessions return
-    case M.lookup token sessions of
-        Nothing      -> error $ "Nonexistant token: " ++ show token
-        Just session -> cont session
-
-{-----------------------------------------------------------------------------
-    Implementation of two-way communication
-    - POST and GET requests
-------------------------------------------------------------------------------}
--- | Route the communication between JavaScript and the server
-routeCommunication :: (Session -> IO a) -> ServerState -> Routes
-routeCommunication worker server =
-    [("/init"   , init worker server)
-    ,("/poll"   , withSession server poll  )
-    ,("/signal" , withSession server signal)
-    ]
-
--- | Make a new session.
-newSession :: ServerState -> (URI,[(String, String)]) -> Integer -> IO Session
-newSession sServerState sStartInfo sToken = do
-    sSignals          <- newChan
-    sInstructions     <- newChan
-    sMutex            <- newMVar ()
-    sEventHandlers    <- newMVar M.empty
-    sElementEvents    <- newMVar M.empty
-    sEventQuit        <- newEvent
-    sElementIds       <- newMVar [0..]
-    now               <- getCurrentTime
-    sConnectedState   <- newMVar (Disconnected now)
-    sThreadId         <- myThreadId
-    sClosures         <- newMVar [0..]
-    let session = Session {..}
-    initializeElementEvents session    
-    return session
-
--- | Make a new session and add it to the server
-createSession :: (Session -> IO void) -> ServerState -> Snap Session
-createSession worker server = do
-    -- uri    <- snapRequestURI
-    let uri = undefined -- FIXME: No URI for WebSocket requests.
-    params <- snapRequestCookies
-    liftIO $ modifyMVar (sSessions server) $ \sessions -> do
-        let newKey = maybe 0 (+1) (lastMay (M.keys sessions))
-        session <- newSession server (uri,params) newKey
-        _       <- forkIO $ void $ worker session >> handleEvents session
-        return (M.insert newKey session sessions, session)
-
--- | Respond to initialization request.
-init :: (Session -> IO void) -> ServerState -> Snap ()
-init worker server = do
-    session <- createSession worker server
-    modifyResponse . setHeader "Set-Token" . fromString . show . sToken $ session
-    poll session
-
-snapRequestURI :: Snap URI
-snapRequestURI = do
-    uri     <- getInput "info"
-    maybe (error ("Unable to parse request URI: " ++ show uri)) return (uri >>= parseURI)
-
-snapRequestCookies :: Snap [(String, String)]
-snapRequestCookies = do
-    cookies <- getsRequest rqCookies
-    return $ flip map cookies $ \Cookie{..} -> (toString cookieName,toString cookieValue)
-
-
--- | Respond to poll requests.
-poll :: Session -> Snap ()
-poll Session{..} = do
-    let setDisconnected = do
-        now <- getCurrentTime
-        modifyMVar_ sConnectedState (const (return (Disconnected now)))
-    
-    instructions <- liftIO $ do
-        modifyMVar_ sConnectedState (const (return Connected))
-        threadId <- myThreadId
-        forkIO $ do
-            delaySeconds $ 60 * 5 -- Force kill after 5 minutes.
-            killThread threadId
-        E.catch (readAvailableChan sInstructions) $ \e -> do
-            -- no instructions available after some time
-            when (e == Control.Exception.ThreadKilled) $ setDisconnected
-            E.throw e
-    
-    writeJson instructions
-
--- | Handle signals sent from the client.
-signal :: Session -> Snap ()
-signal Session{..} = do
-    input <- getInput "signal"
-    case input of
-      Just signalJson -> do
-        let signal = JSON.decode signalJson
-        case signal of
-          Ok signal -> liftIO $ writeChan sSignals signal
-          Error err -> error err
-      Nothing -> error $ "Unable to parse " ++ show input
-
-{-----------------------------------------------------------------------------
-    Implementation of two-way communication
-    - WebSockets
-------------------------------------------------------------------------------}
--- | Route the communication between JavaScript and the server
-routeWebsockets :: (Session -> IO a) -> ServerState -> Routes
-routeWebsockets worker server =
-    [("websocket", response)]
-    where
-    response = do
-        session <- createSession worker server
-        WS.runWebSocketsSnap (webSocket session)
-        error "Threepenny.Internal.Core: runWebSocketsSnap should never return."
-
-
-webSocket :: Session -> WS.Request -> WS.WebSockets WS.Hybi00 ()
-webSocket Session{..} req = void $ do
-    WS.acceptRequest req
-    -- websockets are always connected, don't let the custodian kill you.
-    liftIO $ modifyMVar_ sConnectedState (const (return Connected))
-
-    -- write data (in another thread)
-    send     <- WS.getSink
-    sendData <- liftIO . forkIO . forever $ do
-        x <- readChan sInstructions
-        WS.sendSink send . WS.textData . Text.pack . JSON.encode $ x
-
-    -- read data
-    let readData = do
-            input <- WS.receiveData
-            case input of
-                "ping" -> liftIO . WS.sendSink send . WS.textData . Text.pack $ "pong"
-                "quit" -> WS.throwWsError WS.ConnectionClosed
-                input  -> case JSON.decode . Text.unpack $ input of
-                    Ok signal -> liftIO $ writeChan sSignals signal
-                    Error err -> WS.throwWsError . WS.ParseError $ Atto.ParseError [] err
-    
-    forever readData `WS.catchWsError`
-        \_ -> liftIO $ do
-            killThread sendData             -- kill sending thread when done
-            writeChan sSignals $ Quit ()    -- signal  Quit  event
-
-{-----------------------------------------------------------------------------
-    FFI implementation on top of the communication channel
-------------------------------------------------------------------------------}
--- | Atomically execute the given computation in the context of a browser window
-atomic :: Window -> IO a -> IO a
-atomic window@(Session{..}) m = do
-  takeMVar sMutex
-  ret <- m
-  putMVar sMutex ()
-  return ret
-
--- | Send an instruction and read the signal response.
-call :: Session -> Instruction -> (Signal -> IO (Maybe a)) -> IO a
-call session@(Session{..}) instruction withSignal = do
-  takeMVar sMutex
-  run session $ instruction
-  newChan <- dupChan sSignals
-  go sMutex newChan
-
-  where
-    go mutex newChan = do
-      signal <- readChan newChan
-      result <- withSignal signal
-      case result of
-        Just signal -> do putMVar mutex ()
-                          return signal
-        Nothing     -> go mutex newChan
-            -- keep reading signals from the duplicated channel
-            -- until the function above succeeds
-
--- Run the given instruction wihtout waiting for a response.
-run :: Session -> Instruction -> IO ()
-run (Session{..}) i = writeChan sInstructions i
-
--- | Call the given function with the given continuation. Doesn't block.
-callDeferredFunction
-  :: Window                    -- ^ Browser window
-  -> String                    -- ^ The function name.
-  -> [String]                  -- ^ Parameters.
-  -> ([Maybe String] -> IO ()) -- ^ The continuation to call if/when the function completes.
-  -> IO ()
-callDeferredFunction session@(Session{..}) func params closure = do
-  cid      <- modifyMVar sClosures (\(x:xs) -> return (xs,x))
-  closure' <- newClosure session func (show cid) closure
-  run session $ CallDeferredFunction (closure',func,params)
-
--- | Run the given JavaScript function and carry on. Doesn't block.
---
--- The client window uses JavaScript's @eval()@ function to run the code.
-runFunction :: Window -> JSFunction () -> IO ()
-runFunction session = run session . RunJSFunction . unJSCode . code
-
--- | Run the given JavaScript function and wait for results. Blocks.
---
--- The client window uses JavaScript's @eval()@ function to run the code.
-callFunction :: Window -> JSFunction a -> IO a
-callFunction window (JSFunction code marshal) = 
-    call window (CallJSFunction . unJSCode $ code) $ \signal ->
-        case signal of
-            FunctionResult v -> case marshal window v of
-                Ok    a -> return $ Just a
-                Error _ -> return Nothing
-            _ -> return Nothing
-
-
-{-----------------------------------------------------------------------------
-    Snap utilities
-------------------------------------------------------------------------------}
--- Write JSON to output.
-writeJson :: (MonadSnap m, JSON a) => a -> m ()
-writeJson json = do
-    modifyResponse $ setContentType "application/json"
-    (writeText . pack . (\x -> showJSValue x "") . showJSON) json
-
--- Get a text input from snap.
-getInput :: (MonadSnap f) => ByteString -> f (Maybe String)
-getInput = fmap (fmap (unpack . decodeUtf8)) . getParam
-
--- Read an input from snap.
-readInput :: (MonadSnap f,Read a) => ByteString -> f (Maybe a)
-readInput = fmap (>>= readMay) . getInput
-
-{-----------------------------------------------------------------------------
-    Resourcse
-------------------------------------------------------------------------------}
-type Routes = [(ByteString, Snap ())]
-
-routeResources :: Maybe FilePath -> Maybe FilePath -> ServerState -> Routes
-routeResources customHTML staticDir server =
-    fixHandlers noCache $
-        static ++
-        [("/"                          , root)
-        ,("/driver/threepenny-gui.js"  , writeText jsDriverCode )
-        ,("/driver/threepenny-gui.css" , writeText cssDriverCode)
-        ,("/file/:name"                ,
-            withFilepath (sFiles server) (flip serveFileAs))
-        ,("/dir/:name"                 ,
-            withFilepath (sDirs  server) (\path _ -> serveDirectory path))
-        ]
-    where
-    fixHandlers f routes = [(a,f b) | (a,b) <- routes]
-    noCache h = modifyResponse (setHeader "Cache-Control" "no-cache") >> h
-    
-    static = maybe [] (\dir -> [("/static", serveDirectory dir)]) staticDir
-    
-    root = case customHTML of
-        Just file -> case staticDir of
-            Just dir -> serveFile (dir </> file)
-            Nothing  -> logError "Graphics.UI.Threepenny: Cannot use tpCustomHTML file without tpStatic"
-        Nothing   -> writeText defaultHtmlFile
-
-
--- Get a filename from a URI
-withFilepath :: MVar Filepaths -> (FilePath -> MimeType -> Snap a) -> Snap a
-withFilepath rDict cont = do
-    mName    <- getParam "name"
-    (_,dict) <- liftIO $ withMVar rDict return
-    case (\key -> M.lookup key dict) =<< mName of
-        Just (path,mimetype) -> cont path mimetype
-        Nothing              -> error $ "File not loaded: " ++ show mName
-
--- FIXME: Serving large files fails with the exception
--- System.SendFile.Darwin: invalid argument (Socket is not connected)
-
-
-newAssociation :: MVar Filepaths -> (FilePath, MimeType) -> IO String
-newAssociation rDict (path,mimetype) = do
-    (old, dict) <- takeMVar rDict
-    let new = old + 1; key = show new ++ takeFileName path
-    putMVar rDict $ (new, M.insert (fromString key) (path,mimetype) dict)
-    return key
-
--- | Begin to serve a local file under an URI.
-loadFile :: Session -> MimeType -> FilePath -> IO String
-loadFile Session{..} mimetype path = do
-    key <- newAssociation (sFiles sServerState) (path,mimetype)
-    return $ "/file/" ++ key
-
--- | Begin to serve a local directory under an URI.
-loadDirectory :: Session -> FilePath -> IO String
-loadDirectory Session{..} path = do
-    key <- newAssociation (sDirs sServerState) (path,"")
-    return $ "/dir/" ++ key
-
-
-{-----------------------------------------------------------------------------
-    Event handling
-------------------------------------------------------------------------------}
-{- $eventhandling
-
-    To bind events to elements, use the 'bind' function.
-
-    To handle DOM events, use the 'handleEvent' function, or the
-    'handleEvents' function which will block forever.
-
-    See the rest of this section for some helpful functions that do
-    common binding, such as clicks, hovers, etc.
--}
-
--- | Handle events signalled from the client.
-handleEvents :: Window -> IO ()
-handleEvents window@(Session{..}) = do
-    signal <- getSignal window
-    case signal of
-        Threepenny.Event (elid,eventType,params) -> do
-            handleEvent1 window ((elid,eventType),EventData params)
-            handleEvents window
-        Quit () -> do
-            snd sEventQuit ()
-            -- do not continue handling events
-        _       -> do
-            handleEvents window
-
--- | Add a new event handler for a given key
-addEventHandler :: Window -> (EventKey, Handler EventData) -> IO () 
-addEventHandler Session{..} (key,handler) =
-    modifyMVar_ sEventHandlers $ return .
-        M.insertWith (\h1 h a -> h1 a >> h a) key handler        
-
-
--- | Handle a single event
-handleEvent1 :: Window -> (EventKey,EventData) -> IO ()
-handleEvent1 Session{..} (key,params) = do
-    handlers <- readMVar sEventHandlers
-    case M.lookup key handlers of
-        Just handler -> handler params
-        Nothing      -> return ()
-
--- Get the latest signal sent from the client.
-getSignal :: Window -> IO Signal
-getSignal (Session{..}) = readChan sSignals
-
--- | Bind an event handler for a dom event to an 'Element'.
-bind
-    :: String               -- ^ The eventType, see any DOM documentation for a list of these.
-    -> Element              -- ^ The element to bind to.
-    -> Handler EventData    -- ^ The event handler to bind.
-    -> IO ()
-bind eventType (Element el@(ElementId elid) session) handler = do
-    let key = (elid, eventType)
-    -- register with client if it has never been registered on the server
-    handlers <- readMVar $ sEventHandlers session
-    when (not $ key `M.member` handlers) $
-        run session $ Bind eventType el (Closure key)
-    -- register with server
-    addEventHandler session (key, handler)
-
--- | Register event handler that occurs when the client has disconnected.
-disconnect :: Window -> Event ()
-disconnect = fst . sEventQuit
-
-
-initializeElementEvents :: Window -> IO ()
-initializeElementEvents session@(Session{..}) = do
-        initEvents =<< getHead session
-        initEvents =<< getBody session
-    where
-    initEvents el@(Element elid _) = do
-        x <- newEventsNamed $ \(name,_,handler) -> bind name el handler
-        modifyMVar_ sElementEvents $ return . M.insert elid x
-
--- Make a uniquely numbered event handler.
-newClosure :: Window -> String -> String -> ([Maybe String] -> IO ()) -> IO Closure
-newClosure window eventType elid thunk = do
-    let key = (elid, eventType)
-    addEventHandler window (key, \(EventData xs) -> thunk xs)
-    return (Closure key)
-
-{-----------------------------------------------------------------------------
-    Setting attributes
-------------------------------------------------------------------------------}
-{- $settingattributes
- 
-    Text, HTML and attributes of DOM nodes can be set using the
-    functions in this section. 
--}
-
--- | Set the style of the given element.
-setStyle :: [(String, String)] -- ^ Pairs of CSS (property,value).
-         -> Element            -- ^ The element to update.
-         -> IO ()
-setStyle props e@(Element el session) = run session $ SetStyle el props
-
--- | Set the attribute of the given element.
-setAttr :: String  -- ^ The attribute name.
-        -> String  -- ^ The attribute value.
-        -> Element -- ^ The element to update.
-        -> IO ()
-setAttr key value e@(Element el session) = run session $ SetAttr el key value
-
--- | Set the property of the given element.
-setProp :: String  -- ^ The property name.
-        -> JSValue -- ^ The property value.
-        -> Element -- ^ The element to update.
-        -> IO ()
-setProp key value e@(Element el session) =
-    runFunction session $ ffi "$(%1).prop(%2,%3);" el key value
-
--- | Set the text of the given element.
-setText :: String  -- ^ The plain text.
-        -> Element -- ^ The element to update.
-        -> IO ()
-setText props e@(Element el session) = run session $ SetText el props
-
--- | Set the HTML of the given element.
-setHtml :: String  -- ^ The HTML.
-        -> Element -- ^ The element to update.
-        -> IO ()
-setHtml props e@(Element el session) = run session $ SetHtml el props
-
--- | Set the title of the document.
-setTitle
-    :: String  -- ^ The title.
-    -> Window  -- ^ The document window
-    -> IO ()
-setTitle title session = run session $ SetTitle title
-
--- | Empty the given element.
-emptyEl :: Element -> IO ()
-emptyEl e@(Element el session) = run session $ EmptyEl el
-
--- | Delete the given element.
-delete :: Element -> IO ()
-delete e@(Element el session)  = run session $ Delete el
-
-
-{-----------------------------------------------------------------------------
-    Manipulating tree structure
-------------------------------------------------------------------------------}
--- $treestructure
---
---  Functions for creating, deleting, moving, appending, prepending, DOM nodes.
-
--- | Create a new element of the given tag name.
-newElement :: Window      -- ^ Browser window in which context to create the element
-           -> String      -- ^ The tag name.
-           -> IO Element  -- ^ A tag reference. Non-blocking.
-newElement session@(Session{..}) tagName = do
-    elid <- modifyMVar sElementIds $ \elids ->
-        return (tail elids,"*" ++ show (head elids) ++ ":" ++ tagName)
-    return (Element (ElementId elid) session)
-
--- | Append a child element to a parent element. Non-blocking.
-appendElementTo
-    :: Element     -- ^ Parent.
-    -> Element     -- ^ Child.
-    -> IO () 
-appendElementTo (Element parent session) e@(Element child _) =
-    -- TODO: Right now, parent and child need to be from the same session/browser window
-    --       Implement transfer of elements across browser windows
-    run session $ Append parent child
-
-{-----------------------------------------------------------------------------
-    Querying the DOM
-------------------------------------------------------------------------------}
--- $querying
--- 
--- The DOM can be searched for elements of a given name, and nodes can
--- be inspected for their values.
-
--- | Get all elements of the given tag name.  Blocks.
-getElementsByTagName
-    :: Window        -- ^ Browser window
-    -> String        -- ^ The tag name.
-    -> IO [Element]  -- ^ All elements with that tag name.
-getElementsByTagName window tagName =
-  call window (GetElementsByTagName tagName) $ \signal ->
-    case signal of
-      Elements els -> return $ Just $ [Element el window | el <- els]
-      _            -> return Nothing
-
--- | Get a list of elements by particular IDs.  Blocks.
-getElementsById
-    :: Window        -- ^ Browser window
-    -> [String]      -- ^ The ID string.
-    -> IO [Element]  -- ^ Elements with given ID.
-getElementsById window ids =
-  call window (GetElementsById ids) $ \signal ->
-    case signal of
-      Elements els -> return $ Just [Element el window | el <- els]
-      _            -> return Nothing
-
--- | Get a list of elements by particular class.  Blocks.
-getElementsByClassName
-    :: Window        -- ^ Browser window
-    -> String        -- ^ The class string.
-    -> IO [Element]  -- ^ Elements with given class.
-getElementsByClassName window cls =
-  call window (GetElementsByClassName cls) $ \signal ->
-    case signal of
-      Elements els -> return $ Just [Element el window | el <- els]
-      _            -> return Nothing
-
--- | Get the value of an input. Blocks.
-getValue
-    :: Element   -- ^ The element to get the value of.
-    -> IO String -- ^ The plain text value.
-getValue e@(Element el window) =
-  call window (GetValue el) $ \signal ->
-    case signal of
-      Value str -> return (Just str)
-      _         -> return Nothing
-
--- | Get the property of an element. Blocks.
-getProp
-    :: String     -- ^ The property name.
-    -> Element    -- ^ The element to get the value of.
-    -> IO JSValue -- ^ The plain text value.
-getProp prop e@(Element el window) =
-    callFunction window (ffi "$(%1).prop(%2)" el prop)
-
--- | Get 'Window' associated to an 'Element'.
-getWindow :: Element -> Window
-getWindow (Element _ window) = window
-
--- | Get values from inputs. Blocks. This is faster than many 'getValue' invocations.
-getValuesList
-    :: [Element]   -- ^ A list of elements to get the values of.
-    -> IO [String] -- ^ The list of plain text values.
-getValuesList [] = return []
-getValuesList es@(Element _ window : _) =
-    let elids = [elid | Element elid _ <- es] in
-    call window (GetValues elids) $ \signal ->
-        case signal of
-            Values strs -> return $ Just strs
-            _           -> return Nothing
-
--- | Read a value from an input. Blocks.
-readValue
-    :: Read a
-    => Element      -- ^ The element to read a value from.
-    -> IO (Maybe a) -- ^ Maybe the read value.
-readValue = liftM readMay . getValue
-
--- | Read values from inputs. Blocks. This is faster than many 'readValue' invocations.
-readValuesList
-    :: Read a
-    => [Element]      -- ^ The element to read a value from.
-    -> IO (Maybe [a]) -- ^ Maybe the read values. All or none.
-readValuesList = liftM (sequence . map readMay) . getValuesList
-
--- | Get the head of the page.
-getHead :: Window -> IO Element
-getHead session = return $ Element (ElementId "head") session
-
--- | Get the body of the page.
-getBody :: Window -> IO Element
-getBody session = return $ Element (ElementId "body") session
-
--- | Get the request location.
-getRequestLocation :: Window -> IO URI
-getRequestLocation = return . fst . sStartInfo
-
--- | Get the request cookies.
-getRequestCookies :: Window -> IO [(String,String)]
-getRequestCookies = return . snd . sStartInfo
-
-{-----------------------------------------------------------------------------
-    Utilities
-------------------------------------------------------------------------------}
--- | Send a debug message to the client. The behaviour of the client
---   is unspecified.
-debug
-    :: Window -- ^ Client window
-    -> String -- ^ Some plain text to send to the client.
-    -> IO ()
-debug window = run window . Debug
-
--- | Clear the client's DOM.
-clear :: Window -> IO ()
-clear window = runFunction window $ ffi "$('body').contents().detach()"
diff --git a/src/Graphics/UI/Threepenny/Internal/Driver.hs b/src/Graphics/UI/Threepenny/Internal/Driver.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/UI/Threepenny/Internal/Driver.hs
@@ -0,0 +1,673 @@
+{-# LANGUAGE CPP, PackageImports #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecursiveDo #-}
+{-# OPTIONS -fno-warn-name-shadowing #-}
+
+module Graphics.UI.Threepenny.Internal.Driver
+  (
+  -- * Synopsis
+  -- | The main internal functionality.
+      
+  -- * Server running
+   serve
+  ,loadFile
+  ,loadDirectory
+
+  -- * Elements
+  ,newElement
+  ,appendElementTo
+  ,emptyEl
+  ,delete
+  
+  -- * Event handling
+  -- $eventhandling
+  ,bind
+  ,disconnect
+  ,module Reactive.Threepenny
+ 
+  -- * Querying
+  -- $querying
+  ,getHead
+  ,getBody
+  ,getElementsByTagName
+  ,getElementsById
+  ,getElementsByClassName
+  ,getWindow
+  ,getValuesList
+  ,getRequestCookies
+  ,getRequestLocation
+  
+  -- * Utilities
+  ,debug
+  ,callDeferredFunction
+  ,atomic
+
+  -- * JavaScript FFI
+  ,ToJS, FFI, ffi, JSFunction
+  ,runFunction, callFunction
+  
+  -- * Types
+  ,Window
+  ,Element
+  ,Config(..)
+  ,EventData(..)
+  ) where
+
+
+
+import           Control.Applicative
+import           Control.Concurrent
+import           Control.Concurrent.Chan.Extra
+import           Control.Concurrent.Delay
+import           Control.DeepSeq
+import qualified Control.Exception
+import           Control.Monad
+import           Control.Monad.IO.Class
+import qualified "MonadCatchIO-transformers" Control.Monad.CatchIO as E
+import           Data.ByteString               (ByteString)
+import           Data.ByteString.UTF8          (toString,fromString)
+import           Data.Map                      (Map)
+import qualified Data.Map                      as M
+import           Data.Maybe
+import           Data.Text                     (Text,pack,unpack)
+import qualified Data.Text                     as Text
+import           Data.Text.Encoding
+import           Data.Time
+import           Network.URI
+import qualified Network.WebSockets            as WS
+import qualified Network.WebSockets.Snap       as WS
+import qualified Data.Attoparsec.Enumerator    as Atto
+import           Prelude                       hiding (init)
+import           Safe
+import           Snap.Core
+import qualified Snap.Http.Server              as Snap
+import           Snap.Util.FileServe
+import           System.FilePath
+import qualified Text.JSON as JSON
+import           Text.JSON.Generic
+
+
+import           Graphics.UI.Threepenny.Internal.Types     as Threepenny
+import           Graphics.UI.Threepenny.Internal.Resources
+import           Graphics.UI.Threepenny.Internal.FFI
+import           Reactive.Threepenny
+
+import qualified Foreign.Coupon as Foreign
+import qualified System.Mem
+
+{-----------------------------------------------------------------------------
+    Server and and session management
+------------------------------------------------------------------------------}
+newServerState :: IO ServerState
+newServerState = ServerState 
+    <$> newMVar M.empty
+    <*> newMVar (0,M.empty)
+    <*> newMVar (0,M.empty)
+
+-- | Run a TP server with Snap on the specified port and the given
+--   worker action.
+serve :: Config -> (Session -> IO ()) -> IO ()
+serve Config{..} worker = do
+    server <- newServerState
+    _      <- forkIO $ custodian 30 (sSessions server)
+    let config = Snap.setPort tpPort
+               $ Snap.setErrorLog (Snap.ConfigIoLog tpLog)
+               $ Snap.setAccessLog (Snap.ConfigIoLog tpLog)
+               $ Snap.defaultConfig
+    Snap.httpServe config . route $
+        routeResources tpCustomHTML tpStatic server
+        -- ++ routeCommunication worker server
+        ++ routeWebsockets worker server
+
+-- | Kill sessions after at least n seconds of disconnectedness.
+custodian :: Integer -> MVar Sessions -> IO ()
+custodian seconds sessions = forever $ do
+  delaySeconds seconds
+  modifyMVar_ sessions $ \sessions -> do
+    killed <- fmap catMaybes $ forM (M.assocs sessions) $ \(key,Session{..}) -> do
+      state <- readMVar sConnectedState
+      case state of
+        Connected -> return Nothing
+        Disconnected time -> do
+          now <- getCurrentTime
+          let dcSeconds = diffUTCTime now time
+          -- session is disconnected for more than  seconds
+          if (dcSeconds > fromIntegral seconds)
+             then do killThread sThreadId
+                     return (Just key)
+             else return Nothing
+    
+    -- remove killed sessions from the map
+    return (M.filterWithKey (\k _ -> not (k `elem` killed)) sessions)
+
+-- Run a snap action with the given session.
+withSession :: ServerState -> (Session -> Snap a) -> Snap a
+withSession server cont = do
+    token <- readInput "token"
+    case token of
+        Nothing    -> error $ "Invalid session token format."
+        Just token -> withGivenSession token server cont
+
+-- Do something with the session given by its token id.
+withGivenSession :: Integer -> ServerState -> (Session -> Snap a) -> Snap a
+withGivenSession token ServerState{..} cont = do
+    sessions <- liftIO $ withMVar sSessions return
+    case M.lookup token sessions of
+        Nothing      -> error $ "Nonexistant token: " ++ show token
+        Just session -> cont session
+
+{-----------------------------------------------------------------------------
+    Implementation of two-way communication
+    - POST and GET requests
+------------------------------------------------------------------------------}
+-- | Route the communication between JavaScript and the server
+routeCommunication :: (Session -> IO a) -> ServerState -> Routes
+routeCommunication worker server =
+    [("/init"   , init worker server)
+    ,("/poll"   , withSession server poll  )
+    ,("/signal" , withSession server signal)
+    ]
+
+-- | Make a new session.
+newSession :: ServerState -> (URI,[(String, String)]) -> Integer -> IO Session
+newSession sServerState sStartInfo sToken = do
+    sSignals          <- newChan
+    sInstructions     <- newChan
+    sMutex            <- newMVar ()
+    sEventQuit        <- newEvent
+    sPrizeBooth      <- Foreign.newPrizeBooth
+    let sHeadElement  =  undefined -- filled in later
+    let sBodyElement  =  undefined
+    now               <- getCurrentTime
+    sConnectedState   <- newMVar (Disconnected now)
+    sThreadId         <- myThreadId
+    sClosures         <- newMVar [0..]
+    let session = Session {..}
+    initializeElements session    
+
+-- | Make a new session and add it to the server
+createSession :: (Session -> IO void) -> ServerState -> Snap Session
+createSession worker server = do
+    -- uri    <- snapRequestURI
+    let uri = undefined -- FIXME: No URI for WebSocket requests.
+    params <- snapRequestCookies
+    liftIO $ modifyMVar (sSessions server) $ \sessions -> do
+        let newKey = maybe 0 (+1) (lastMay (M.keys sessions))
+        session <- newSession server (uri,params) newKey
+        _       <- forkIO $ void $ worker session >> handleEvents session
+        return (M.insert newKey session sessions, session)
+
+-- | Respond to initialization request.
+init :: (Session -> IO void) -> ServerState -> Snap ()
+init worker server = do
+    session <- createSession worker server
+    modifyResponse . setHeader "Set-Token" . fromString . show . sToken $ session
+    poll session
+
+snapRequestURI :: Snap URI
+snapRequestURI = do
+    uri     <- getInput "info"
+    maybe (error ("Unable to parse request URI: " ++ show uri)) return (uri >>= parseURI)
+
+snapRequestCookies :: Snap [(String, String)]
+snapRequestCookies = do
+    cookies <- getsRequest rqCookies
+    return $ flip map cookies $ \Cookie{..} -> (toString cookieName,toString cookieValue)
+
+
+-- | Respond to poll requests.
+poll :: Session -> Snap ()
+poll Session{..} = do
+    let setDisconnected = do
+        now <- getCurrentTime
+        modifyMVar_ sConnectedState (const (return (Disconnected now)))
+    
+    instructions <- liftIO $ do
+        modifyMVar_ sConnectedState (const (return Connected))
+        threadId <- myThreadId
+        forkIO $ do
+            delaySeconds $ 60 * 5 -- Force kill after 5 minutes.
+            killThread threadId
+        E.catch (readAvailableChan sInstructions) $ \e -> do
+            -- no instructions available after some time
+            when (e == Control.Exception.ThreadKilled) $ setDisconnected
+            E.throw e
+    
+    writeJson instructions
+
+-- | Handle signals sent from the client.
+signal :: Session -> Snap ()
+signal Session{..} = do
+    input <- getInput "signal"
+    case input of
+      Just signalJson -> do
+        let signal = JSON.decode signalJson
+        case signal of
+          Ok signal -> liftIO $ writeChan sSignals signal
+          Error err -> error err
+      Nothing -> error $ "Unable to parse " ++ show input
+
+{-----------------------------------------------------------------------------
+    Implementation of two-way communication
+    - WebSockets
+------------------------------------------------------------------------------}
+-- | Route the communication between JavaScript and the server
+routeWebsockets :: (Session -> IO a) -> ServerState -> Routes
+routeWebsockets worker server =
+    [("websocket", response)]
+    where
+    response = do
+        session <- createSession worker server
+        WS.runWebSocketsSnap (webSocket session)
+        error "Threepenny.Internal.Core: runWebSocketsSnap should never return."
+
+
+webSocket :: Session -> WS.PendingConnection -> IO ()
+webSocket Session{..} request = void $ do
+    connection <- WS.acceptRequest request
+    -- websockets are always connected, don't let the custodian kill you.
+    modifyMVar_ sConnectedState (const (return Connected))
+
+    -- write data (in another thread)
+    sendData <- forkIO . forever $ do
+        x <- readChan sInstructions
+        -- see note [Instruction strictness]
+        WS.sendTextData connection . Text.pack . JSON.encode $ x
+
+    -- read data
+    let readData = do
+            input <- WS.receiveData connection
+            case input of
+                "ping" -> WS.sendTextData connection . Text.pack $ "pong"
+                "quit" -> E.throw WS.ConnectionClosed
+                input  -> case JSON.decode . Text.unpack $ input of
+                    Ok signal -> writeChan sSignals signal
+                    Error err -> E.throw $ Atto.ParseError [] err
+    
+    forever readData `E.finally`
+        (do
+            killThread sendData             -- kill sending thread when done
+            writeChan sSignals $ Quit ()    -- signal  Quit  event
+        )
+
+{- note [Instruction strictness]
+
+The  Instruction  may contain components that evaluate to _|_.
+An exception will be thrown when we try to send one of those to the browser.
+However, the  WS.sendSink  function is called in a different thread
+than where the faulty instruction was constructed.
+We want to throw an exception in the latter thread.
+Hence, we make sure that the  Instruction  is fully evaluated (deepseq)
+before passing it to the thread that sends it to the web browser.
+
+(Another, probably preferred, solution would be to make the  Instruction
+data type fully strict by default.)
+
+-}
+
+
+
+{-----------------------------------------------------------------------------
+    FFI implementation on top of the communication channel
+------------------------------------------------------------------------------}
+-- | Atomically execute the given computation in the context of a browser window
+atomic :: Window -> IO a -> IO a
+atomic window@(Session{..}) m = do
+  takeMVar sMutex
+  ret <- m
+  putMVar sMutex ()
+  return ret
+
+-- | Send an instruction and read the signal response.
+call :: Session -> Instruction -> (Signal -> IO (Maybe a)) -> IO a
+call session@(Session{..}) instruction withSignal = do
+  -- see note [Instruction strictness]
+  Control.Exception.evaluate $ force instruction
+  takeMVar sMutex
+  writeChan sInstructions instruction
+  newChan <- dupChan sSignals
+  go sMutex newChan
+
+  where
+    go mutex newChan = do
+      signal <- readChan newChan
+      result <- withSignal signal
+      case result of
+        Just signal -> do putMVar mutex ()
+                          return signal
+        Nothing     -> go mutex newChan
+            -- keep reading signals from the duplicated channel
+            -- until the function above succeeds
+
+-- Run the given instruction wihtout waiting for a response.
+run :: Session -> Instruction -> IO ()
+run (Session{..}) instruction =
+    writeChan sInstructions $!! instruction  -- see note [Instruction strictness]
+
+-- | Call the given function with the given continuation. Doesn't block.
+callDeferredFunction
+  :: Window                    -- ^ Browser window
+  -> String                    -- ^ The function name.
+  -> [String]                  -- ^ Parameters.
+  -> ([Maybe String] -> IO ()) -- ^ The continuation to call if/when the function completes.
+  -> IO ()
+callDeferredFunction window fun params thunk = do
+    closure <- newClosure window fun $ \(EventData xs) -> thunk xs
+    run window $ CallDeferredFunction (closure,fun,params)
+
+-- | Run the given JavaScript function and carry on. Doesn't block.
+--
+-- The client window uses JavaScript's @eval()@ function to run the code.
+runFunction :: Window -> JSFunction () -> IO ()
+runFunction session = run session . RunJSFunction . toCode
+
+-- | Run the given JavaScript function and wait for results. Blocks.
+--
+-- The client window uses JavaScript's @eval()@ function to run the code.
+callFunction :: Window -> JSFunction a -> IO a
+callFunction window jsfunction = 
+    call window (CallJSFunction . toCode $ jsfunction) $ \signal ->
+        case signal of
+            FunctionResult v -> case marshalResult jsfunction window v of
+                Ok    a -> return $ Just a
+                Error _ -> return Nothing
+            _ -> return Nothing
+
+
+-- | Package a Haskell function such that it can be called from JavaScript.
+-- 
+-- At the moment, we implement this as an event handler that is
+-- attached to the @head@ element.
+newClosure
+    :: Window               -- ^ Browser window context
+    -> String               -- ^ Function name (for debugging).
+    -> (EventData -> IO ()) -- ^ Function to call
+    -> IO Closure
+newClosure window@(Session{..}) fun thunk = do
+    cid <- modifyMVar sClosures $ \(x:xs) -> return (xs,x)
+    let eventId = fun ++ "-" ++ show cid
+    attachClosure sHeadElement eventId thunk
+    return $ Closure (unprotectedGetElementId sHeadElement, eventId)
+
+
+{-----------------------------------------------------------------------------
+    Snap utilities
+------------------------------------------------------------------------------}
+-- Write JSON to output.
+writeJson :: (MonadSnap m, JSON a) => a -> m ()
+writeJson json = do
+    modifyResponse $ setContentType "application/json"
+    (writeText . pack . (\x -> showJSValue x "") . showJSON) json
+
+-- Get a text input from snap.
+getInput :: (MonadSnap f) => ByteString -> f (Maybe String)
+getInput = fmap (fmap (unpack . decodeUtf8)) . getParam
+
+-- Read an input from snap.
+readInput :: (MonadSnap f,Read a) => ByteString -> f (Maybe a)
+readInput = fmap (>>= readMay) . getInput
+
+{-----------------------------------------------------------------------------
+    Resourcse
+------------------------------------------------------------------------------}
+type Routes = [(ByteString, Snap ())]
+
+routeResources :: Maybe FilePath -> Maybe FilePath -> ServerState -> Routes
+routeResources customHTML staticDir server =
+    fixHandlers noCache $
+        static ++
+        [("/"                          , root)
+        ,("/driver/threepenny-gui.js"  , writeText jsDriverCode )
+        ,("/driver/threepenny-gui.css" , writeText cssDriverCode)
+        ,("/file/:name"                ,
+            withFilepath (sFiles server) (flip serveFileAs))
+        ,("/dir/:name"                 ,
+            withFilepath (sDirs  server) (\path _ -> serveDirectory path))
+        ]
+    where
+    fixHandlers f routes = [(a,f b) | (a,b) <- routes]
+    noCache h = modifyResponse (setHeader "Cache-Control" "no-cache") >> h
+    
+    static = maybe [] (\dir -> [("/static", serveDirectory dir)]) staticDir
+    
+    root = case customHTML of
+        Just file -> case staticDir of
+            Just dir -> serveFile (dir </> file)
+            Nothing  -> logError "Graphics.UI.Threepenny: Cannot use tpCustomHTML file without tpStatic"
+        Nothing   -> writeText defaultHtmlFile
+
+
+-- Get a filename from a URI
+withFilepath :: MVar Filepaths -> (FilePath -> MimeType -> Snap a) -> Snap a
+withFilepath rDict cont = do
+    mName    <- getParam "name"
+    (_,dict) <- liftIO $ withMVar rDict return
+    case (\key -> M.lookup key dict) =<< mName of
+        Just (path,mimetype) -> cont path mimetype
+        Nothing              -> error $ "File not loaded: " ++ show mName
+
+-- FIXME: Serving large files fails with the exception
+-- System.SendFile.Darwin: invalid argument (Socket is not connected)
+
+
+newAssociation :: MVar Filepaths -> (FilePath, MimeType) -> IO String
+newAssociation rDict (path,mimetype) = do
+    (old, dict) <- takeMVar rDict
+    let new = old + 1; key = show new ++ takeFileName path
+    putMVar rDict $ (new, M.insert (fromString key) (path,mimetype) dict)
+    return key
+
+-- | Begin to serve a local file under an URI.
+loadFile :: Session -> MimeType -> FilePath -> IO String
+loadFile Session{..} mimetype path = do
+    key <- newAssociation (sFiles sServerState) (path,mimetype)
+    return $ "/file/" ++ key
+
+-- | Begin to serve a local directory under an URI.
+loadDirectory :: Session -> FilePath -> IO String
+loadDirectory Session{..} path = do
+    key <- newAssociation (sDirs sServerState) (path,"")
+    return $ "/dir/" ++ key
+
+
+{-----------------------------------------------------------------------------
+    Elements
+        Creation, Management, Finalization
+------------------------------------------------------------------------------}
+-- | Create a new element of the given tag name.
+newElement :: Window        -- ^ Browser window in which context to create the element
+           -> String        -- ^ The tag name.
+           -> Events        -- ^ Events associated to that element.
+           -> IO Element    -- ^ A tag reference. Non-blocking.
+newElement elSession@(Session{..}) elTagName elEvents = do
+    elHandlers <- newMVar M.empty
+    el         <- Foreign.newItem sPrizeBooth ElementData{..}
+    Foreign.addFinalizer el $ delete el
+        -- FIXME: Do not try to delete elements from the session when
+        -- the session is broken/disconnected already.
+        -- A fix should be part of the  run  function, though.
+    return el
+
+-- | Get 'Window' associated to an 'Element'.
+getWindow :: Element -> IO Window
+getWindow e = withElement e $ \_ window -> return window
+
+-- | Look up several elements in the browser window.
+lookupElements :: Session -> [ElementId] -> IO [Element]
+lookupElements window = mapM (flip lookupElement window)
+
+-- | Append a child element to a parent element. Non-blocking.
+appendElementTo
+    :: Element     -- ^ Parent.
+    -> Element     -- ^ Child.
+    -> IO ()
+appendElementTo eParent eChild =
+    -- TODO: Right now, parent and child need to be from the same session/browser window
+    --       Implement transfer of elements across browser windows
+    withElement eParent $ \parent session ->
+    withElement eChild  $ \child  _       -> do
+        Foreign.addReachable eParent eChild
+        runFunction session $ ffi "$(%1).append($(%2))" parent child
+
+-- | Get the head of the page.
+getHead :: Window -> IO Element
+getHead session = return $ sHeadElement session
+
+-- | Get the body of the page.
+getBody :: Window -> IO Element
+getBody session = return $ sBodyElement session
+
+-- | Empty the given element.
+emptyEl :: Element -> IO ()
+emptyEl el = withElement el $ \elid window -> do
+    Foreign.clearReachable el
+    runFunction window $ ffi "$(%1).contents().detach()" elid
+
+-- | Delete the given element.
+delete :: Element -> IO ()
+delete el = withElement el $ \elid window ->
+    run window $ Delete elid
+    -- Note: We want a primitive 'Delete' here, because 
+    -- we do not want the implicit conversion from ElementId to element.
+
+
+{-----------------------------------------------------------------------------
+    Event handling
+------------------------------------------------------------------------------}
+{- $eventhandling
+
+    To bind events to elements, use the 'bind' function.
+
+    To handle DOM events, use the 'handleEvent' function, or the
+    'handleEvents' function which will block forever.
+
+    See the rest of this section for some helpful functions that do
+    common binding, such as clicks, hovers, etc.
+-}
+
+-- | Handle events signalled from the client.
+handleEvents :: Window -> IO ()
+handleEvents window@(Session{..}) = do
+    signal <- getSignal window
+    case signal of
+        Threepenny.Event elid eventId params -> do
+            handleEvent1 window (elid,eventId,EventData params)
+#ifdef REBUG
+            -- debug garbage collection of elements:
+            System.Mem.performGC
+#endif
+            handleEvents window
+        Quit () -> do
+            snd sEventQuit ()
+            -- do not continue handling events
+        _       -> do
+            handleEvents window
+
+-- | Handle a single event.
+handleEvent1 :: Window -> (ElementId, EventId, EventData) -> IO ()
+handleEvent1 window (elid,eventId,params) = do
+    el <- lookupElement elid window
+    withElementData el $ \_ eldata -> do
+        handlers <- readMVar $ elHandlers eldata
+        case M.lookup eventId handlers of
+            Just handler -> handler params
+            Nothing      -> return ()
+
+-- Get the latest signal sent from the client.
+getSignal :: Window -> IO Signal
+getSignal (Session{..}) = readChan sSignals
+
+-- | Associate a new closure with an element.
+attachClosure :: Element -> EventId -> Handler EventData -> IO () 
+attachClosure el eventId handler = withElementData el $ \_ eldata ->
+    modifyMVar_ (elHandlers eldata) $ return .
+        M.insertWith (\h1 h a -> h1 a >> h a) eventId handler
+
+-- | Bind an event handler for a dom event to an 'Element'.
+bind
+    :: EventId              -- ^ The eventType, see any DOM documentation for a list of these.
+    -> Element              -- ^ The element to bind to.
+    -> Handler EventData    -- ^ The event handler to bind.
+    -> IO ()
+bind eventId e handler = withElementData e $ \elid el -> do
+    handlers <- readMVar $ elHandlers el
+    -- register with client if it has never been registered on the server
+    when (not $ eventId `M.member` handlers) $
+        run (elSession el) $ Bind eventId elid
+    -- register with server
+    attachClosure e eventId handler
+
+-- | Register event handler that occurs when the client has disconnected.
+disconnect :: Window -> Event ()
+disconnect = fst . sEventQuit
+
+-- | Initialize the 'head' and 'body' elements when the session starts.
+initializeElements :: Session -> IO Session
+initializeElements session@(Session{..}) = do
+        sHeadElement <- createElement "head"
+        sBodyElement <- createElement "body"
+        return $ Session{..}
+    where
+    newEvents     e   = newEventsNamed $ \(name,_,handler) -> bind name e handler
+    createElement tag = mdo
+        x <- newElement session tag =<< newEvents x
+        return x
+
+{-----------------------------------------------------------------------------
+    Querying the DOM
+------------------------------------------------------------------------------}
+-- $querying
+-- 
+-- The DOM can be searched for elements of a given name, and nodes can
+-- be inspected for their values.
+
+-- | Get all elements of the given tag name. Blocks.
+getElementsByTagName :: Window -> String -> IO [Element]
+getElementsByTagName window tag = do
+    elids <- callFunction window $ ffi "document.getElementsByTagName(%1)" tag
+    lookupElements window elids
+
+-- | Get a list of elements by particular IDs.  Blocks.
+getElementsById :: Window -> [String] -> IO [Element]
+getElementsById window ids = do
+    elids <- forM ids $ \x ->
+        callFunction window $ ffi "[document.getElementById(%1)]" x
+    lookupElements window $ concat elids
+
+-- | Get a list of elements by particular class.  Blocks.
+getElementsByClassName :: Window -> String -> IO [Element]
+getElementsByClassName window cls = do
+    elids <- callFunction window $ ffi "document.getElementsByClassName(%1)" cls
+    lookupElements window elids
+
+-- | Get values from inputs. Blocks. This is faster than many @getValue@ invocations.
+getValuesList
+    :: [Element]   -- ^ A list of elements to get the values of.
+    -> IO [String] -- ^ The list of plain text values.
+getValuesList []        = return []
+getValuesList es@(e0:_) = withElement e0 $ \_ window -> do
+    let elids  = map unprotectedGetElementId es
+    call window (GetValues elids) $ \signal ->
+        case signal of
+            Values strs -> return $ Just strs
+            _           -> return Nothing
+
+-- | Get the request location.
+getRequestLocation :: Window -> IO URI
+getRequestLocation = return . fst . sStartInfo
+
+-- | Get the request cookies.
+getRequestCookies :: Window -> IO [(String,String)]
+getRequestCookies = return . snd . sStartInfo
+
+{-----------------------------------------------------------------------------
+    Utilities
+------------------------------------------------------------------------------}
+-- | Send a debug message to the client. The behaviour of the client
+--   is unspecified.
+debug
+    :: Window -- ^ Client window
+    -> String -- ^ Some plain text to send to the client.
+    -> IO ()
+debug window = run window . Debug
diff --git a/src/Graphics/UI/Threepenny/Internal/FFI.hs b/src/Graphics/UI/Threepenny/Internal/FFI.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/UI/Threepenny/Internal/FFI.hs
@@ -0,0 +1,130 @@
+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+module Graphics.UI.Threepenny.Internal.FFI (
+    -- * Synopsis
+    -- | Combinators for creating JavaScript code and marhsalling.
+    
+    -- * Documentation
+    ffi,
+    FFI(..), ToJS(..),
+    JSFunction,
+    
+    toCode, marshalResult,
+    ) where
+
+import           Data.Functor
+import           Data.ByteString       (ByteString)
+import qualified Data.ByteString.Char8 as BS
+import           Text.JSON.Generic
+
+import Graphics.UI.Threepenny.Internal.Types
+
+{-----------------------------------------------------------------------------
+    JavaScript Code and Foreign Function Interface
+------------------------------------------------------------------------------}
+-- | JavaScript code snippet.
+newtype JSCode = JSCode { unJSCode :: String }
+    deriving (Eq, Ord, Show, Data, Typeable)
+
+-- | Helper class for rendering Haskell values as JavaScript expressions.
+class ToJS a where
+    render :: a -> JSCode
+
+instance ToJS String     where render   = JSCode . show
+instance ToJS Int        where render   = JSCode . show
+instance ToJS Bool       where render b = JSCode $ if b then "false" else "true"
+instance ToJS JSValue    where render x = JSCode $ showJSValue x ""
+instance ToJS ByteString where render   = JSCode . show
+instance ToJS ElementId  where
+    render (ElementId x) = apply "elidToElement(%1)" [render x]
+instance ToJS Element    where render = render . unprotectedGetElementId
+
+
+-- | A JavaScript function with a given output type @a@.
+data JSFunction a = JSFunction
+    { code    :: JSCode                          -- code snippet
+    , marshal :: Window -> JSValue -> Result a   -- convert to Haskell value
+    }
+
+-- | Render function to a textual representation using JavaScript syntax.
+toCode :: JSFunction a -> String
+toCode = unJSCode . code
+
+-- | Convert function result to a Haskell value.
+marshalResult
+    :: JSFunction a -- ^ Function that has been executed
+    -> Window       -- ^ Browser context
+    -> JSValue      -- ^ JSON representation of the return value 
+    -> Result a     -- ^ 
+marshalResult = marshal
+
+instance Functor JSFunction where
+    fmap f = fmapWindow (const f)
+
+fmapWindow :: (Window -> a -> b) -> JSFunction a -> JSFunction b
+fmapWindow f (JSFunction c m) = JSFunction c (\w v -> f w <$> m w v)
+
+fromJSCode :: JSCode -> JSFunction ()
+fromJSCode c = JSFunction { code = c, marshal = \_ _ -> Ok () }
+
+-- | Helper class for making 'ffi' a variable argument function.
+class FFI a where
+    fancy :: ([JSCode] -> JSCode) -> a
+
+instance (ToJS a, FFI b) => FFI (a -> b) where
+    fancy f a = fancy $ f . (render a:)
+
+instance FFI (JSFunction ())         where fancy f = fromJSCode $ f []
+instance FFI (JSFunction String)     where fancy   = mkResult "%1.toString()"
+instance FFI (JSFunction JSValue)    where fancy   = mkResult "%1"
+instance FFI (JSFunction [ElementId]) where fancy  = mkResult "elementsToElids(%1)"
+
+-- FIXME: We need access to IO in order to turn a Coupon into an Element.
+{- 
+instance FFI (JSFunction Element)   where
+    fancy   = fmapWindow (\w elid -> Element elid w) . fancy
+-}
+
+mkResult :: JSON a => String -> ([JSCode] -> JSCode) -> JSFunction a
+mkResult client f = JSFunction
+    { code    = apply client [f []]
+    , marshal = \w -> readJSON
+    }
+
+-- | Simple JavaScript FFI with string substitution.
+--
+-- Inspired by the Fay language. <http://fay-lang.org/>
+--
+-- > example :: String -> Int -> JSFunction String
+-- > example = ffi "$(%1).prop('checked',%2)"
+--
+-- The 'ffi' function takes a string argument representing the JavaScript
+-- code to be executed on the client.
+-- Occurrences of the substrings @%1@ to @%9@ will be replaced by
+-- subequent arguments.
+--
+-- Note: Always specify a type signature! The types automate
+-- how values are marshalled between Haskell and JavaScript.
+-- The class instances for the 'FFI' class show which conversions are supported.
+--
+ffi :: FFI a => String -> a
+ffi macro = fancy (apply macro)
+
+testFFI :: String -> Int -> JSFunction String
+testFFI = ffi "$(%1).prop('checked',%2)"
+
+-- | String substitution.
+-- Substitute occurences of %1, %2 up to %9 with the argument strings.
+-- The types ensure that the % character has no meaning in the generated output.
+-- 
+-- > apply "%1 and %2" [x,y] = x ++ " and " ++ y
+apply :: String -> [JSCode] -> JSCode
+apply code args = JSCode $ go code
+    where
+    argument i = unJSCode (args !! i)
+    
+    go []         = []
+    go ('%':c:cs) = argument index ++ go cs
+        where index = fromEnum c - fromEnum '1'
+    go (c:cs)     = c : go cs
+
diff --git a/src/Graphics/UI/Threepenny/Internal/Include.hs b/src/Graphics/UI/Threepenny/Internal/Include.hs
--- a/src/Graphics/UI/Threepenny/Internal/Include.hs
+++ b/src/Graphics/UI/Threepenny/Internal/Include.hs
@@ -2,13 +2,14 @@
 module Graphics.UI.Threepenny.Internal.Include (include) where
  
 import Data.Functor
+import System.IO
 import qualified Language.Haskell.TH as TH
 import Language.Haskell.TH.Quote
 
 #ifdef CABAL
 root = "src/"
 #else
-root = ""
+root = "../src/" -- running examples from ghci
 #endif
 
 include = QuasiQuoter
@@ -18,4 +19,9 @@
         , quoteDec  = undefined
         }
     where
-    f s = TH.LitE . TH.StringL <$> TH.runIO (readFile $ root ++ s)
+    f s = TH.LitE . TH.StringL <$> TH.runIO (readFileUTF8 $ root ++ s)
+
+readFileUTF8 path = do
+    h <- openFile path ReadMode
+    hSetEncoding h utf8
+    hGetContents h
diff --git a/src/Graphics/UI/Threepenny/Internal/Types.hs b/src/Graphics/UI/Threepenny/Internal/Types.hs
--- a/src/Graphics/UI/Threepenny/Internal/Types.hs
+++ b/src/Graphics/UI/Threepenny/Internal/Types.hs
@@ -1,5 +1,6 @@
+{-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
+{-# LANGUAGE OverloadedStrings #-}
 
 module Graphics.UI.Threepenny.Internal.Types where
 
@@ -7,33 +8,43 @@
 
 import Control.Applicative
 import Control.Concurrent
-import qualified Reactive.Threepenny as E
-import Data.ByteString               (ByteString, hPut)
-import Data.Map                      (Map)
-import Data.String                   (fromString)
+import Control.DeepSeq
+import qualified Reactive.Threepenny    as E
+import           Data.ByteString.Char8  (ByteString)
+import qualified Data.ByteString.Char8  as BS
+import Data.Map                         (Map)
+import Data.String                      (fromString)
 import Data.Time
 
 import Network.URI
 import Text.JSON.Generic
 import System.IO (stderr)
+import System.IO.Unsafe
 
+import qualified Foreign.Coupon as Foreign
+
 {-----------------------------------------------------------------------------
-    Public types
+    Elements and ElementIds
 ------------------------------------------------------------------------------}
-
 -- | Reference to an element in the DOM of the client window.
-data Element = Element
-    { elId      :: ElementId
-    , elSession :: Session
+type Element     = Foreign.Item ElementData
+data ElementData = ElementData
+    { elTagName  :: String          -- element is a <tag>..</tag> element
+    , elSession  :: Session         -- associated browser window
+    , elHandlers :: MVar Handlers   -- event handlers associated with that element
+    , elEvents   :: Events          -- events         associated with that element
     }
+newtype ElementId = ElementId BS.ByteString
+    deriving (Data,Typeable,Show,Eq,Ord)
 
-instance Show Element where
-    show = show . elId
+instance NFData ElementId where rnf (ElementId x) = rnf x
 
--- | An opaque reference to an element in the DOM.
-data ElementId = ElementId String
-  deriving (Data,Typeable,Show,Eq,Ord)
+type EventId  = String
+type Handlers = Map EventId (E.Handler EventData)
+type Events   = EventId -> E.Event EventData
 
+
+-- Marshalling ElementId
 instance JSON ElementId where
   showJSON (ElementId o) = showJSON o
   readJSON obj = do
@@ -41,16 +52,54 @@
     ElementId <$> valFromObj "Element" obj
 
 
--- | A client session. This type is opaque, you don't need to inspect it.
+-- | Perform an action on the element.
+-- The element is not garbage collected while the action is run.
+withElementData :: Element -> (ElementId -> ElementData -> IO a) -> IO a
+withElementData e f = Foreign.withItem e $ \coupon el ->
+    let elid = ElementId $ case fromString (elTagName el) of
+            ""     -> coupon
+            "head" -> "head"
+            "body" -> "body" 
+            tag    -> BS.concat ["*",coupon,":",tag]
+    in f elid el
+
+-- | Special case of 'withElementData'.
+withElement :: Element -> (ElementId -> Session -> IO b) -> IO b
+withElement e f = withElementData e $ \elid el -> f elid (elSession el)
+
+-- | Get 'ElementId' without any guarantee that the element is still alive.
+unprotectedGetElementId :: Element -> ElementId
+unprotectedGetElementId e = unsafePerformIO . withElement e $ \elid _ -> return elid
+
+
+-- | Look up an element in the browser window.
+lookupElement :: ElementId -> Session -> IO Element
+lookupElement (ElementId xs) Session{..} = case xs of
+        "head"      -> return sHeadElement
+        "body"      -> return sBodyElement
+        xs          -> maybe (error msg) id <$> Foreign.lookup (coupon xs) sPrizeBooth
+    where
+    coupon xs = if BS.head xs == '*'
+        then BS.takeWhile (/= ':') . BS.tail $ xs
+        else xs
+
+    msg = "Graphics.UI.Threepenny: Fatal error: ElementId " ++ show xs
+        ++ "was garbage collected on the server, but is still present in the browser."
+
+
+{-----------------------------------------------------------------------------
+    Server
+------------------------------------------------------------------------------}
+-- | A client session.
 data Session = Session
   { sSignals        :: Chan Signal
   , sInstructions   :: Chan Instruction
   , sMutex          :: MVar ()
-  , sEventHandlers  :: MVar (Map EventKey (E.Handler EventData))
-  , sElementEvents  :: MVar (Map ElementId ElementEvents)
   , sEventQuit      :: (E.Event (), E.Handler ())
   , sClosures       :: MVar [Integer]
-  , sElementIds     :: MVar [Integer]
+  , sPrizeBooth     :: Foreign.PrizeBooth ElementData
+  , sHeadElement    :: Element
+  , sBodyElement    :: Element
   , sToken          :: Integer
   , sConnectedState :: MVar ConnectedState
   , sThreadId       :: ThreadId
@@ -62,19 +111,12 @@
 type MimeType      = ByteString
 type Filepaths     = (Integer, Map ByteString (FilePath, MimeType))
 
-type EventKey      = (String, String)
-type ElementEvents = String -> E.Event EventData
-
 data ServerState = ServerState
     { sSessions :: MVar Sessions
     , sFiles    :: MVar Filepaths
     , sDirs     :: MVar Filepaths
     }
 
-
--- | The client browser window.
-type Window = Session
-
 data ConnectedState
   = Disconnected UTCTime -- ^ The time that the poll disconnected, or
                          -- the first initial connection time.
@@ -82,6 +124,20 @@
                          -- since when.
   deriving (Show)
 
+
+-- | An opaque reference to a closure that the event manager uses to
+--   trigger events signalled by the client.
+data Closure = Closure (ElementId,EventId)
+    deriving (Typeable,Data,Show)
+
+instance NFData Closure where rnf (Closure x) = rnf x
+
+{-----------------------------------------------------------------------------
+    Public types
+------------------------------------------------------------------------------}
+-- | The client browser window.
+type Window = Session
+
 -- | Data from an event. At the moment it is empty.
 data EventData = EventData [Maybe String]
 
@@ -101,34 +157,22 @@
     { tpPort       = 10000
     , tpCustomHTML = Nothing
     , tpStatic     = Nothing
-    , tpLog        = \s -> hPut stderr s >> hPut stderr (fromString "\n")
+    , tpLog        = \s -> BS.hPut stderr s >> BS.hPut stderr "\n"
     }
 
 
 {-----------------------------------------------------------------------------
     Communication between client and server
 ------------------------------------------------------------------------------}
-
 -- | An instruction that is sent to the client as JSON.
 data Instruction
   = Debug String
   | SetToken Integer
-  | GetElementsByClassName String
-  | GetElementsById [String]
-  | GetElementsByTagName String
-  | SetStyle ElementId [(String,String)]
-  | SetAttr ElementId String String
-  | Append ElementId ElementId
-  | SetText ElementId String
-  | SetHtml ElementId String
-  | Bind String ElementId Closure
-  | GetValue ElementId
+  | Bind EventId ElementId
   | GetValues [ElementId]
-  | SetTitle String
   | RunJSFunction String
   | CallJSFunction String
   | CallDeferredFunction (Closure,String,[String])
-  | EmptyEl ElementId
   | Delete ElementId
   deriving (Typeable,Data,Show)
 
@@ -136,12 +180,20 @@
     readJSON _ = error "JSON.Instruction.readJSON: No method implemented."
     showJSON x = toJSON x 
 
+instance NFData Instruction where
+    rnf (Debug    x  ) = rnf x
+    rnf (SetToken x  ) = rnf x
+    rnf (Bind     x y) = rnf x `seq` rnf y
+    rnf (GetValues xs) = rnf xs
+    rnf (RunJSFunction  x) = rnf x
+    rnf (CallJSFunction x) = rnf x
+    rnf (CallDeferredFunction x) = rnf x
+    rnf (Delete x)     = rnf x
+
 -- | A signal (mostly events) that are sent from the client to the server.
 data Signal
   = Quit ()
-  | Elements [ElementId]
-  | Event (String,String,[Maybe String])
-  | Value String
+  | Event ElementId EventId [Maybe String]
   | Values [String]
   | FunctionCallValues [Maybe String]
   | FunctionResult JSValue
@@ -152,119 +204,21 @@
   readJSON obj = do
     obj <- readJSON obj
     let quit     = Quit <$> valFromObj "Quit" obj
-        elements = Elements <$> valFromObj "Elements" obj
         event = do
-          (cid,typ,arguments) <- valFromObj "Event" obj
-          args <- mapM nullable arguments
-          return $ Event (cid,typ,args)
-        value = Value <$> valFromObj "Value" obj
+          e         <- valFromObj "Event" obj
+          elid      <- valFromObj "Element" e
+          eventId   <- valFromObj "EventId" e
+          arguments <- valFromObj "Params"  e
+          args      <- mapM nullable arguments
+          return $ Event elid eventId args
         values = Values <$> valFromObj "Values" obj
         fcallvalues = do
           FunctionCallValues <$> (valFromObj "FunctionCallValues" obj >>= mapM nullable)
         fresult = FunctionResult <$> valFromObj "FunctionResult" obj
-    quit <|> elements <|> event <|> value <|> values <|> fcallvalues <|> fresult
+    quit <|> event <|> values <|> fcallvalues <|> fresult
 
 -- | Read a JSValue that may be null.
 nullable :: JSON a => JSValue -> Result (Maybe a)
 nullable JSNull = return Nothing
 nullable v      = Just <$> readJSON v
-
--- | An opaque reference to a closure that the event manager uses to
---   trigger events signalled by the client.
-data Closure = Closure EventKey
-    deriving (Typeable,Data,Show)
-
-{-----------------------------------------------------------------------------
-    JavaScript Code and Foreign Function Interface
-------------------------------------------------------------------------------}
--- | JavaScript code snippet.
-newtype JSCode = JSCode { unJSCode :: String }
-    deriving (Eq, Ord, Show, Data, Typeable)
-
--- | Class for rendering Haskell types as JavaScript code.
-class ToJS a where
-    render :: a -> JSCode
-
-instance ToJS String    where render   = JSCode . show
-instance ToJS Int       where render   = JSCode . show
-instance ToJS Bool      where render b = JSCode $ if b then "false" else "true"
-instance ToJS JSValue   where render x = JSCode $ showJSValue x ""
-instance ToJS ElementId where
-    render (ElementId x) = apply "elidToElement(%1)" [render x]
-instance ToJS Element   where render (Element e _) = render e
-
-
--- | Representation of a JavaScript expression
--- with a girven output type.
-data JSFunction a = JSFunction
-    { code    :: JSCode                          -- code snippet
-    , marshal :: Window -> JSValue -> Result a   -- convert to Haskell value
-    }
-
-instance Functor JSFunction where
-    fmap f = fmapWindow (const f)
-
-fmapWindow :: (Window -> a -> b) -> JSFunction a -> JSFunction b
-fmapWindow f (JSFunction c m) = JSFunction c (\w v -> f w <$> m w v)
-
-fromJSCode :: JSCode -> JSFunction ()
-fromJSCode c = JSFunction { code = c, marshal = \_ _ -> Ok () }
-
--- | Helper class for making a simple JavaScript FFI
-class FFI a where
-    fancy :: ([JSCode] -> JSCode) -> a
-
-instance (ToJS a, FFI b) => FFI (a -> b) where
-    fancy f a = fancy $ f . (render a:)
-
-instance FFI (JSFunction ())        where fancy f = fromJSCode $ f []
-instance FFI (JSFunction String)    where fancy   = mkResult "%1.toString()"
-instance FFI (JSFunction JSValue)   where fancy   = mkResult "%1"
-instance FFI (JSFunction ElementId) where
-    fancy   = mkResult "{ Element: elementToElid(%1) }"
-instance FFI (JSFunction Element)   where
-    fancy   = fmapWindow (\w elid -> Element elid w) . fancy
-
-mkResult :: JSON a => String -> ([JSCode] -> JSCode) -> JSFunction a
-mkResult client f = JSFunction
-    { code    = apply client [f []]
-    , marshal = \w -> readJSON
-    }
-
--- | Simple JavaScript FFI with string substitution.
---
--- Inspired by the Fay language. <http://fay-lang.org/>
---
--- > example :: String -> Int -> JSFunction String
--- > example = ffi "$(%1).prop('checked',%2)"
---
--- The 'ffi' function takes a string argument representing the JavaScript
--- code to be executed on the client.
--- Occurrences of the substrings @%1@ to @%9@ will be replaced by
--- subequent arguments.
---
--- Note: Always specify a type signature! The types automate
--- how values are marshalled between Haskell and JavaScript.
--- The class instances for the 'FFI' class show which conversions are supported.
---
-ffi :: FFI a => String -> a
-ffi macro = fancy (apply macro)
-
-testFFI :: String -> Int -> JSFunction String
-testFFI = ffi "$(%1).prop('checked',%2)"
-
--- | String substitution.
--- Substitute occurences of %1, %2 up to %9 with the argument strings.
--- The types ensure that the % character has no meaning in the generated output.
--- 
--- > apply "%1 and %2" [x,y] = x ++ " and " ++ y
-apply :: String -> [JSCode] -> JSCode
-apply code args = JSCode $ go code
-    where
-    argument i = unJSCode (args !! i)
-    
-    go []         = []
-    go ('%':c:cs) = argument index ++ go cs
-        where index = fromEnum c - fromEnum '1'
-    go (c:cs)     = c : go cs
 
diff --git a/src/Graphics/UI/Threepenny/JQuery.hs b/src/Graphics/UI/Threepenny/JQuery.hs
--- a/src/Graphics/UI/Threepenny/JQuery.hs
+++ b/src/Graphics/UI/Threepenny/JQuery.hs
@@ -6,7 +6,7 @@
 import Data.Default
 import Data.Maybe
 import Graphics.UI.Threepenny.Core
-import qualified Graphics.UI.Threepenny.Internal.Core as Core
+import qualified Graphics.UI.Threepenny.Internal.Driver as Core
 import qualified Graphics.UI.Threepenny.Internal.Types as Core
 import Text.JSON
 import Reactive.Threepenny
@@ -20,10 +20,10 @@
 -- | Animate property changes of a function.
 animate :: Element -> [(String,String)] -> Int -> Easing -> IO () -> IO ()
 animate el props duration easing complete =
-    flip updateElement el $ \(Core.Element el window) ->
+    Core.withElement (toElement el) $ \elid window ->
         callDeferredFunction window
             "jquery_animate"
-            [encode el,encode (makeObj (map (second showJSON) props)),show duration,map toLower (show easing)]
+            [encode elid,encode (makeObj (map (second showJSON) props)),show duration,map toLower (show easing)]
             (const complete)
 
 -- | Fade in an element.
@@ -43,11 +43,9 @@
     f (EventData x) = concat . catMaybes $ x
 
 -- | Focus an element.
-setFocus :: Element -> IO ()
-setFocus = updateElement $ \(Core.Element el window) ->
-    runFunction window (ffi "$(%1).focus()" el)
+setFocus :: Element -> UI ()
+setFocus = runFunction . ffi "$(%1).focus()"
 
 -- | Scroll to the bottom of an element.
-scrollToBottom :: Element -> IO ()
-scrollToBottom = updateElement $ \(Core.Element area window) ->
-    runFunction window (ffi "jquery_scrollToBottom(%1)" area)
+scrollToBottom :: Element -> UI ()
+scrollToBottom = runFunction . ffi "jquery_scrollToBottom(%1)"
diff --git a/src/Graphics/UI/Threepenny/Timer.hs b/src/Graphics/UI/Threepenny/Timer.hs
--- a/src/Graphics/UI/Threepenny/Timer.hs
+++ b/src/Graphics/UI/Threepenny/Timer.hs
@@ -28,8 +28,8 @@
     } deriving (Typeable)
 
 -- | Create a new timer
-timer :: IO Timer
-timer = do
+timer :: UI Timer
+timer = liftIO $ do
     tvRunning     <- newTVarIO False
     tvInterval    <- newTVarIO 1000
     (tTick, fire) <- newEvent
@@ -60,11 +60,11 @@
 running = fromGetSet tRunning
 
 -- | Start the timer.
-start :: Timer -> IO ()
+start :: Timer -> UI ()
 start = set' running True
 
 -- | Stop the timer.
-stop :: Timer -> IO ()
+stop :: Timer -> UI ()
 stop = set' running False
 
 fromTVar :: TVar a -> GetSet a a
@@ -73,15 +73,18 @@
 type GetSet i o = (IO o, i -> IO ())
 
 fromGetSet :: (x -> GetSet i o) -> ReadWriteAttr x i o
-fromGetSet f = mkReadWriteAttr (fst . f) (\i x -> snd (f x) i)
+fromGetSet f = mkReadWriteAttr (liftIO . fst . f) (\i x -> liftIO $ snd (f x) i)
 
 
 {-----------------------------------------------------------------------------
     Small test
 ------------------------------------------------------------------------------}
+{-
+
 testTimer = do
     t <- timer
     void $ register (tick t) $ const $ putStr "Hello"
     return t
         # set interval 1000
         # set running True
+-}
diff --git a/src/Graphics/UI/Threepenny/Widgets.hs b/src/Graphics/UI/Threepenny/Widgets.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/UI/Threepenny/Widgets.hs
@@ -0,0 +1,120 @@
+{-# LANGUAGE RecordWildCards, ScopedTypeVariables #-}
+module Graphics.UI.Threepenny.Widgets (
+    -- * Synopsis
+    -- | Widgets are reusable building blocks for a graphical user interface.
+    -- This module collects useful widgets that are designed to work
+    -- with functional reactive programming (FRP).
+    -- 
+    -- For more details and information on how to write your own widgets, see the
+    -- <https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/doc/design-widgets.md
+    -- widget design guide>.
+    
+    -- * Tidings
+    Tidings, rumors, facts, tidings,
+    -- * Widgets
+    -- ** Input widgets
+    TextEntry, entry, userText,
+    -- ** ListBox
+    ListBox, listBox, userSelection,
+    ) where
+
+import Control.Monad (void, when)
+import qualified Data.Map                          as Map
+
+import qualified Graphics.UI.Threepenny.Attributes as UI
+import qualified Graphics.UI.Threepenny.Events     as UI
+import qualified Graphics.UI.Threepenny.Elements   as UI
+import Graphics.UI.Threepenny.Core
+import Reactive.Threepenny
+
+{-----------------------------------------------------------------------------
+    Input widgets
+------------------------------------------------------------------------------}
+-- | A single-line text entry.
+data TextEntry = TextEntry
+    { _elementTE :: Element
+    , _userTE    :: Tidings String
+    }
+
+instance Widget TextEntry where getElement = _elementTE
+
+-- | User changes to the text value.
+userText :: TextEntry -> Tidings String
+userText = _userTE
+
+-- | Create a single-line text entry.
+entry
+    :: Behavior String  -- ^ Display value when the element does not have focus.
+    -> UI TextEntry
+entry bValue = do -- single text entry
+    input <- UI.input
+
+    bEditing <- stepper False $ and <$>
+        unions [True <$ UI.focus input, False <$ UI.blur input]
+    
+    window <- askWindow
+    liftIOLater $ onChange bValue $ \s -> runUI window $ do
+        editing <- liftIO $ currentValue bEditing
+        when (not editing) $ void $ element input # set value s
+
+    let _elementTE = input
+        _userTE    = tidings bValue $ UI.valueChange input 
+    return TextEntry {..}
+
+{-----------------------------------------------------------------------------
+    List box
+------------------------------------------------------------------------------}
+-- | A list of values. The user can select entries.
+data ListBox a = ListBox
+    { _elementLB   :: Element
+    , _selectionLB :: Tidings (Maybe a)
+    }
+
+instance Widget (ListBox a) where getElement = _elementLB
+
+-- | User changes to the current selection (possibly empty).
+userSelection :: ListBox a -> Tidings (Maybe a)
+userSelection = _selectionLB
+
+-- | Create a 'ListBox'.
+listBox :: forall a. Ord a
+    => Behavior [a]               -- ^ list of items
+    -> Behavior (Maybe a)         -- ^ selected item
+    -> Behavior (a -> UI Element) -- ^ display for an item
+    -> UI (ListBox a)
+listBox bitems bsel bdisplay = do
+    list <- UI.select
+
+    -- animate output items
+    element list # sink items (map <$> bdisplay <*> bitems)
+
+    -- animate output selection
+    let bindices :: Behavior (Map.Map a Int)
+        bindices = (Map.fromList . flip zip [0..]) <$> bitems
+        bindex   = lookupIndex <$> bindices <*> bsel
+
+        lookupIndex indices Nothing    = Nothing
+        lookupIndex indices (Just sel) = Map.lookup sel indices
+
+    element list # sink UI.selection bindex
+
+    -- changing the display won't change the current selection
+    -- eDisplay <- changes display
+    -- sink listBox [ selection :== stepper (-1) $ bSelection <@ eDisplay ]
+
+    -- user selection
+    let bindices2 :: Behavior (Map.Map Int a)
+        bindices2 = Map.fromList . zip [0..] <$> bitems
+
+        _selectionLB = tidings bsel $
+            lookupIndex <$> bindices2 <@> UI.selectionChange list
+        _elementLB   = list
+
+    return ListBox {..}
+
+items = mkWriteAttr $ \i x -> void $ do
+    return x # set children [] #+ map (\i -> UI.option #+ [i]) i
+
+
+
+
diff --git a/src/Graphics/UI/driver.js b/src/Graphics/UI/driver.js
--- a/src/Graphics/UI/driver.js
+++ b/src/Graphics/UI/driver.js
@@ -39,7 +39,7 @@
   ////////////////////////////////////////////////////////////////////////////////
   // State
   var sessionToken = null;
-  var element_count = 0, el_table = {};
+  var el_table = {};
   var tp_enable_log = $.cookie('tp_log') == "true";
   var signal_count = 0;
 
@@ -160,8 +160,13 @@
       ws.close();
     });
     
-    var sendEvent = function (e) {
-      ws.send(JSON.stringify({ Event : e}));
+    var sendEvent = function (elid, key, params) {
+      ws.send(JSON.stringify({ Event : 
+          { Element : { Element : elid }
+          , EventId : key
+          , Params  : params
+          }
+        }));
     }
     var reply     = function (response) {
       if (response != undefined)
@@ -202,26 +207,17 @@
     console_log("Event: %s",JSON.stringify(event));
     for(var key in event){
       switch(key){
-                
-      case "EmptyEl": {
-        var id = event.EmptyEl;
-        var el = elidToElement(id);
-        // Detach child elements without deleting associated event handlers and data.
-        // It is not correct to remove the child elements from the el_table
-        // because they may still be present on the server side.
-        $(el).contents().detach();
-        reply();
-        break;
-      }
+
       case "CallDeferredFunction": {
-        var call = event.CallDeferredFunction;
-        var closure = call[0];
+        // FIXME: CallDeferredFunction probably doesn't work right now.
+        var call        = event.CallDeferredFunction;
+        var closure     = call[0];
         var theFunction = eval(call[1]);
-        var params = call[2];
+        var params      = call[2];
         theFunction.apply(window, params.concat(function(){
           console_log(this);
           var args = Array.prototype.slice.call(arguments,0);
-          sendEvent(closure.concat([args]));
+          sendEvent(closure[0],closure[1],args);
         }));
         reply();
         break;
@@ -237,7 +233,7 @@
         break;
       }
       case "Delete": {
-        event_delete(event);
+        deleteElid(event.Delete);
         reply();
         break;
       }
@@ -247,74 +243,6 @@
         reply();
         break;
       }
-      case "GetElementsByTagName": {
-        var elements = document.getElementsByTagName(event.GetElementsByTagName);
-        var els = [];
-        var len = elements.length;
-        for(var i = 0; i < len; i++) {
-          els.push({
-            Element: elementToElid(elements[i])
-          });
-        }
-        reply({ Elements: els });
-        break;
-      }
-      case "GetElementsById": {
-        // Note that this is the html ID, not the elid that is the key of the el_table.
-        var ids = event.GetElementsById;
-        var els = [];
-        for(var i = 0; i < ids.length; i++) {
-            var match = document.getElementById(ids[i]);
-            if (match != null) {
-                els.push({
-                  Element: elementToElid(match)
-                });
-            }
-        }
-        reply({ Elements: els });
-        break;
-      }
-      case "GetElementsByClassName": {
-        var elements = document.getElementsByClassName(event.GetElementsByClassName);
-        var els = [];
-        var len = elements.length;
-        for(var i = 0; i < len; i++) {
-          els.push({
-            Element: elementToElid(elements[i])
-          });
-        }
-        reply({ Elements: els });
-        break;
-      }
-      case "SetStyle": {
-        var set = event.SetStyle;
-        var id = set[0];
-        var style = set[1];
-        var el = elidToElement(id);
-        var len = style.length;
-        for(var i = 0; i < len; i++){
-          el.style[style[i][0]] = style[i][1];
-        }
-        reply();
-        break;
-      }
-      case "SetAttr": {
-        var set   = event.SetAttr;
-        var id    = set[0];
-        var key   = set[1];
-        var value = set[2];
-        var el    = elidToElement(id);
-        $(el).attr(key,value);
-        reply();
-        break;
-      }
-      case "GetValue": {
-        var id = event.GetValue;
-        var el = elidToElement(id);
-        var value = $(el).val();
-        reply({ Value: value });
-        break;
-      }
       case "GetValues": {
         var ids = event.GetValues;
         var len = ids.length;
@@ -325,66 +253,46 @@
         reply({ Values: values });
         break;
       }
-      case "Append": {
-        var append = event.Append;
-        $(elidToElement(append[0])).append($(elidToElement(append[1])));
-        reply();
-        break;
-      }
-      case "SetText": {
-        var set = event.SetText;
-        $(elidToElement(set[0])).text(set[1]);
-        reply();
-        break;
-      }
-      case "SetTitle": {
-        document.title = event.SetTitle;
-        reply();
-        break;
-      }
-      case "SetHtml": {
-        var set = event.SetHtml;
-        $(elidToElement(set[0])).html(set[1]);
-        reply();
-        break;
-      }
       case "Bind": {
         var bind        = event.Bind;
         var eventType   = bind[0];
-        var handlerGuid = bind[2];
-        var el = elidToElement(bind[1]);
+        var elid        = bind[1];
+        var el          = elidToElement(elid);
         console_log('event type: ' + eventType);
         if(eventType == 'livechange') {
           $(el).livechange(300,function(e){
-            sendEvent( handlerGuid.concat([[$(el).val()]]) );
+            sendEvent(elid,eventType, [$(el).val()]);
             return true;
           });
         } else if(eventType == 'sendvalue') {
           $(el).sendvalue(function(x){
-            sendEvent( handlerGuid.concat([[x]]) );
+            sendEvent(elid,eventType, [x]);
           });
         } else if(eventType.match('dragstart|dragenter|dragover|dragleave|drag|drop|dragend')) {
           $(el).bind(eventType,function(e){
-            sendEvent( handlerGuid.concat([
+            sendEvent(elid,eventType,
                 e.originalEvent.dataTransfer
-                    ?[e.originalEvent.dataTransfer.getData("dragData")]
-                    :[]])
+                    ? [e.originalEvent.dataTransfer.getData("dragData")]
+                    : []
               );
             return true;
           });
-        } else if(eventType.match('mousemove')) {
+        } else if(eventType.match('mousemove|mousedown|mouseup')) {
           $(el).bind(eventType,function(e){
-            sendEvent( handlerGuid.concat([[e.pageX.toString(), e.pageY.toString()]]) );
+            var offset = $(this).offset();
+            var x      = e.pageX - offset.left;
+            var y      = e.pageY - offset.top;         
+            sendEvent(elid,eventType, [x.toString(), y.toString()]);
             return true;
           });
         } else if(eventType.match('keydown|keyup')) {
           $(el).bind(eventType,function(e){
-            sendEvent( handlerGuid.concat([[e.keyCode.toString()]]) );
+            sendEvent(elid,eventType, [e.keyCode.toString()]);
             return true;
           });
         } else {
           $(el).bind(eventType,function(e){
-            sendEvent( handlerGuid.concat([e.which?[e.which.toString()]:[]]) );
+            sendEvent(elid,eventType, e.which ? [e.which.toString()] : []);
             return true;
           });
         }
@@ -408,9 +316,9 @@
       return document.body;
     else if(elid == 'head')
       return document.head;
-    else if(el_table[elid]){
+    else if(el_table[elid])
       return el_table[elid];
-    } else {
+    else {
       if(elid[0] == '*'){
         var create = elid.split(':');
         var element = document.createElement(create[1]);
@@ -422,44 +330,47 @@
       }
     }
   }
-  function deleteElementTable(elid){
-    delete el_table[elid];
-  }
-  
+ 
   // Get/generate a elid for an element.  This function is used for cases in which the
   // element is accessed without knowing an elid from the server, such as when the 
   // element is retrieved by type or html ID attribute.  The element is then added to 
   // elid lookup table using the new elid.
   // Note: The mapping between  elids  and  DOM elements  must be bijective.
   function elementToElid(element){
-    if(element.elid) {
-        return element.elid;
-	}
-	else if (element === document.body) {
-        return "body";
+    if(element.elid)
+      return element.elid;
+	  else if (element === document.body)
+      return "body";
+	  else if (element === document.head)
+      return "head";
+    else {
+      throw "Element requested, but does not have elid: " + element;
     }
-	else if (element === document.head) {
-        return "head";
+  }
+  
+  // plural of the mapping from elements to elids
+  function elementsToElids(elements){
+    var els = [], match;
+    for(var i = 0; i < elements.length; i++) {
+      match = elements[i];
+      if (match != null) {
+        els.push({ Element: elementToElid(match) });
+      }
     }
-    else {
-        var elid = "!" + element_count.toString();
-        element_count++;
-        element.elid   = elid;
-        el_table[elid] = element;
-        return elid;
+    return els;
+  }
+  
+  // Delete element from the table
+  function deleteElid(elid){
+    var el = el_table[elid];
+    if (el) {
+      $(el).detach(); // Should be detached already, but make sure
+      delete el_table[elid];
     }
   }
 
   ////////////////////////////////////////////////////////////////////////////////
   // FFI - additional primitive functions
-  
-  function event_delete(event){
-    var id = event.Delete;
-    var el = elidToElement(id);
-    // TODO: Think whether it is correct to remove element ids
-    $(el).detach();
-    deleteElementTable(id);
-  }
   
   window.jquery_animate = function(el_id,props,duration,easing,complete){
     var el = elidToElement(JSON.parse(el_id));
diff --git a/src/MissingDollars.hs b/src/MissingDollars.hs
deleted file mode 100644
--- a/src/MissingDollars.hs
+++ /dev/null
@@ -1,140 +0,0 @@
-{-# LANGUAGE CPP, PackageImports #-}
-
-import Control.Monad
-import Safe
-
-#ifdef CABAL
-import qualified  "threepenny-gui" Graphics.UI.Threepenny as UI
-import "threepenny-gui" Graphics.UI.Threepenny.Core
-#else
-import qualified Graphics.UI.Threepenny as UI
-import Graphics.UI.Threepenny.Core
-#endif
-import Paths
-
-{-----------------------------------------------------------------------------
-    Missing Dollars
-------------------------------------------------------------------------------}
-main :: IO ()
-main = do
-    static <- getStaticDir
-    startGUI defaultConfig
-        { tpPort       = 10000
-        , tpStatic     = Just static
-        } setup
-
-
-setup :: Window -> IO ()
-setup w = void $ do
-    return w # set title "Missing Dollars"
-    UI.addStyleSheet w "missing-dollars.css"
-    
-    (headerView,headerMe) <- mkHeader
-    riddle                <- mkMissingDollarRiddle headerMe
-    let layout = [element headerView] ++ riddle ++ attributionSource        
-    getBody w #+ [UI.div #. "wrap" #+ layout]
-
-
-mkHeader :: IO (Element, Element)
-mkHeader = do
-    headerMe <- string "..."
-    view     <- UI.h1   #+ [string "The ", element headerMe, string " Dollars"]
-    return (view, headerMe)
-
-attributionSource :: [IO Element]
-attributionSource =
-    [ UI.p #+
-        [ UI.anchor #. "view-source" # set UI.href urlSource
-            #+ [string "View source code"]
-        ]
-    , UI.p #+
-        [ string "Originally by "
-        , UI.anchor # set UI.href urlAttribution #+ [string "Albert Lai"]
-        ]
-    ]
-  where
-    urlSource      = "https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/MissingDollars.hs"
-    urlAttribution = "http://www.vex.net/~trebla/humour/missing_dollar.html"
-
-
-mkMissingDollarRiddle :: Element -> IO [IO Element]
-mkMissingDollarRiddle headerMe = do
-    -- declare input and display values
-    (hotelOut : hotelCost : hotelHold : _)
-        <- sequence . replicate 3 $
-            UI.input # set (attr "size") "3" # set (attr "type") "text"
-
-    (hotelChange : hotelRet     : hotelBal : hotelPocket :
-     hotelBal2   : hotelPocket2 : hotelSum : hotelMe     : _)
-        <- sequence . replicate 8 $ UI.span
-    
-    -- update procedure
-    let updateDisplay out cost hold = do
-        let change = out - cost
-            ret    = change - hold
-            bal    = out - ret
-            sum    = bal + hold
-            diff   = sum - out
-        element hotelOut     # set value (show out)
-        element hotelCost    # set value (show cost)
-        element hotelHold    # set value (show hold)
-        element hotelChange  # set text  (show change)
-        element hotelRet     # set text  (show ret)
-        element hotelBal     # set text  (show bal)
-        element hotelPocket  # set text  (show hold)
-        element hotelBal2    # set text  (show bal)
-        element hotelPocket2 # set text  (show hold)
-        element hotelSum     # set text  (show sum)
-        
-        if diff >= 0
-           then do element hotelMe  # set text ("extra $" ++ show diff ++ " come from")
-                   element headerMe # set text "Extra"
-           else do element hotelMe  # set text ("missing $" ++ show (-diff) ++ " go")
-                   element headerMe # set text "Missing"
-        return ()
-    
-    -- initialize values
-    updateDisplay 30 25 2
-    
-    -- calculate button
-    calculate <- UI.button #+ [string "Calculate"]
-    on UI.click calculate $ \_ -> do
-        result <- mapM readMay `liftM` getValuesList [hotelOut,hotelCost,hotelHold]
-        case result of
-            Just [getout,getcost,gethold] -> updateDisplay getout getcost gethold
-            _ -> return ()
-    
-    return $
-        [ UI.h2 #+ [string "The Guests, The Bellhop, And The Pizza"]
-        , UI.p  #+
-            [ string "Three guests went to a hotel and gave $"
-            , element hotelOut
-            , string " to the bellhop to buy pizza. The pizza cost only $"
-            , element hotelCost
-            , string ". Of the $"
-            , element hotelChange
-            , string " change, the bellhop kept $"
-            , element hotelHold
-            , string " to himself and returned $"
-            , element hotelRet
-            , string " to the guests."
-            ]
-        , UI.p  #+
-            [ string "So the guests spent $"
-            , element hotelBal
-            , string ", and the bellhop pocketed $"
-            , element hotelPocket
-            , string ". Now "
-            , string "$"
-            , element hotelBal2
-            , string "+$"
-            , element hotelPocket2
-            , string "=$"
-            , element hotelSum
-            , string ". Where did the "
-            , element hotelMe
-            , string "?"
-            ]
-        , element calculate
-        ]    
-
diff --git a/src/Paths.hs b/src/Paths.hs
deleted file mode 100644
--- a/src/Paths.hs
+++ /dev/null
@@ -1,20 +0,0 @@
-{-# LANGUAGE CPP#-}
-module Paths (getStaticDir) where
-
-import Control.Monad
-import System.FilePath
-
-#if CABAL
--- using cabal
-import qualified Paths_threepenny_gui (getDataDir)
-
-getStaticDir :: IO FilePath
-getStaticDir = (</> "wwwroot") `liftM` Paths_threepenny_gui.getDataDir
-
-#else
--- using GHCi
-
-getStaticDir :: IO FilePath
-getStaticDir = return "../wwwroot/"
-
-#endif
diff --git a/src/Reactive/Threepenny.hs b/src/Reactive/Threepenny.hs
--- a/src/Reactive/Threepenny.hs
+++ b/src/Reactive/Threepenny.hs
@@ -35,6 +35,9 @@
     -- * Additional Notes
     -- $recursion
     
+    -- * Tidings
+    Tidings, tidings, facts, rumors,
+    
     -- * Internal
     -- | Functions reserved for special circumstances.
     -- Do not use unless you know what you're doing.
@@ -43,6 +46,7 @@
 
 import Control.Applicative
 import Control.Monad (void)
+import Control.Monad.IO.Class
 import Data.IORef
 import qualified Data.Map as Map
 
@@ -140,8 +144,8 @@
     register e (\_ -> h =<< Prim.readLatch l)
 
 -- | Read the current value of a 'Behavior'.
-currentValue :: Behavior a -> IO a
-currentValue (B l _) = Prim.readLatch l
+currentValue :: MonadIO m => Behavior a -> m a
+currentValue (B l _) = liftIO $ Prim.readLatch l
 
 
 {-----------------------------------------------------------------------------
@@ -150,7 +154,8 @@
 instance Functor Event where
     fmap f e = E $ liftMemo1 (Prim.mapP f) (unE e)
 
-unsafeMapIO f e   = E $ liftMemo1 (Prim.unsafeMapIOP f) (unE e)
+unsafeMapIO :: (a -> IO b) -> Event a -> Event b
+unsafeMapIO f e = E $ liftMemo1 (Prim.unsafeMapIOP f) (unE e)
 
 -- | Event that never occurs.
 -- Think of it as @never = []@.
@@ -201,8 +206,8 @@
 -- 
 -- Note that the value of the behavior changes \"slightly after\"
 -- the events occur. This allows for recursive definitions.
-accumB :: a -> Event (a -> a) -> IO (Behavior a)
-accumB a e = do
+accumB :: MonadIO m => a -> Event (a -> a) -> m (Behavior a)
+accumB a e = liftIO $ do
     (l1,p1) <- Prim.accumL a =<< at (unE e)
     p2      <- Prim.mapP (const ()) p1
     return $ B l1 (E $ fromPure p2)
@@ -217,7 +222,7 @@
 -- Note that the smaller-than-sign in the comparision @timex < time@ means 
 -- that the value of the behavior changes \"slightly after\"
 -- the event occurrences. This allows for recursive definitions.
-stepper :: a -> Event a -> IO (Behavior a)
+stepper :: MonadIO m => a -> Event a -> m (Behavior a)
 stepper a e = accumB a (const <$> e)
 
 -- | The 'accumE' function accumulates a stream of events.
@@ -228,8 +233,8 @@
 --
 -- Note that the output events are simultaneous with the input events,
 -- there is no \"delay\" like in the case of 'accumB'.
-accumE :: a -> Event (a -> a) -> IO (Event a)
-accumE a e = do
+accumE :: MonadIO m =>  a -> Event (a -> a) -> m (Event a)
+accumE a e = liftIO $ do
     p <- fmap snd . Prim.accumL a =<< at (unE e)
     return $ E $ fromPure p
 
@@ -327,11 +332,41 @@
 -}
 
 -- | Efficient combination of 'accumE' and 'accumB'.
-mapAccum :: acc -> Event (acc -> (x,acc)) -> IO (Event x, Behavior acc)
+mapAccum :: MonadIO m => acc -> Event (acc -> (x,acc)) -> m (Event x, Behavior acc)
 mapAccum acc ef = do
     e <- accumE (undefined,acc) ((. snd) <$> ef)
     b <- stepper acc (snd <$> e)
     return (fst <$> e, b)
+
+
+{-----------------------------------------------------------------------------
+    Tidings
+------------------------------------------------------------------------------}
+-- | Data type representing a behavior ('facts')
+-- and suggestions to change it ('rumors').
+data Tidings a = T { facts :: Behavior a, rumors :: Event a }
+
+-- | Smart constructor. Combine facts and rumors into 'Tidings'.
+tidings :: Behavior a -> Event a -> Tidings a
+tidings b e = T b e
+
+instance Functor Tidings where
+    fmap f (T b e) = T (fmap f b) (fmap f e)
+
+-- | The applicative instance combines 'rumors'
+-- and uses 'facts' when some of the 'rumors' are not available.
+instance Applicative Tidings where
+    pure x  = T (pure x) never
+    f <*> x = uncurry ($) <$> pair f x
+
+pair :: Tidings a -> Tidings b -> Tidings (a,b)
+pair (T bx ex) (T by ey) = T b e
+    where
+    b = (,) <$> bx <*> by
+    x = flip (,) <$> by <@> ex
+    y = (,) <$> bx <@> ey
+    e = unionWith (\(x,_) (_,y) -> (x,y)) x y
+
 
 {-----------------------------------------------------------------------------
     Test
diff --git a/src/Reactive/Threepenny/Monads.hs b/src/Reactive/Threepenny/Monads.hs
new file mode 100644
--- /dev/null
+++ b/src/Reactive/Threepenny/Monads.hs
@@ -0,0 +1,12 @@
+module Reactive.Threepenny.Monads where
+
+import Control.Monad.Trans.RWS.Lazy
+import Reactive.Threepenny.Types
+
+{-----------------------------------------------------------------------------
+    EvalP - evaluate pulses
+------------------------------------------------------------------------------}
+runEvalP :: Values -> EvalP a -> IO (a, Values)
+runEvalP pulses m = do
+    (a, s, w) <- runRWST m () pulses
+    return (a, s)
diff --git a/src/Reactive/Threepenny/PulseLatch.hs b/src/Reactive/Threepenny/PulseLatch.hs
--- a/src/Reactive/Threepenny/PulseLatch.hs
+++ b/src/Reactive/Threepenny/PulseLatch.hs
@@ -14,48 +14,29 @@
 import Control.Monad.Trans.Class
 import Control.Monad.Trans.RWS     as Monad
 
-import Data.Hashable
 import Data.IORef
 import Data.Monoid (Endo(..))
 
-import Data.Unique.Really
-import qualified Data.Vault.Lazy   as Vault
-import qualified Data.HashMap.Lazy as Map
-
-type Vault = Vault.Vault
-type Map   = Map.HashMap
+import           Data.Hashable
+import qualified Data.HashMap.Strict as Map
+import qualified Data.Vault.Strict   as Vault
+import           Data.Unique.Really
 
+import Reactive.Threepenny.Monads
+import Reactive.Threepenny.Types
 
-type Build = IO
+type Map = Map.HashMap
 
 {-----------------------------------------------------------------------------
     Pulse
 ------------------------------------------------------------------------------}
-type EvalP = Monad.RWST () () Vault IO
-
-runEvalP :: Vault -> EvalP a -> IO (a, Vault)
-runEvalP pulses m = do
-    (a, s, w) <- Monad.runRWST m () pulses
-    return (a, s)
-
-
-type Handler  = EvalP (IO ())
-data Priority = DoLatch | DoIO deriving (Eq,Show,Ord,Enum)
-
-instance Hashable Priority where hashWithSalt _ = fromEnum
-
-data Pulse a = Pulse
-    { addHandlerP :: ((Unique, Priority), Handler) -> Build ()
-    , evalP       :: EvalP (Maybe a)
-    }
-
 -- Turn evaluation action into pulse that caches the value.
 cacheEval :: EvalP (Maybe a) -> Build (Pulse a)
 cacheEval e = do
     key <- Vault.newKey
     return $ Pulse
         { addHandlerP = \_ -> return ()
-        , evalP = do
+        , evalP       = do
             vault <- Monad.get
             case Vault.lookup key vault of
                 Just a  -> return a
@@ -76,11 +57,6 @@
     case ma of
         Just a  -> return (f a)
         Nothing -> return $ return ()
-
-{-----------------------------------------------------------------------------
-    Latch
-------------------------------------------------------------------------------}
-data Latch a = Latch { readL :: IO a }
 
 {-----------------------------------------------------------------------------
     Interface to the outside world.
diff --git a/src/Reactive/Threepenny/Types.hs b/src/Reactive/Threepenny/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Reactive/Threepenny/Types.hs
@@ -0,0 +1,39 @@
+module Reactive.Threepenny.Types where
+
+import Control.Monad.Trans.RWS.Lazy
+import Data.Functor.Identity
+
+import           Data.Hashable
+import qualified Data.Vault.Strict   as Vault.Strict
+import           Data.Unique.Really
+
+{-----------------------------------------------------------------------------
+    Pulse and Latch
+------------------------------------------------------------------------------}
+type Values = Vault.Strict.Vault
+
+type Handler  = EvalP (IO ())
+data Priority = DoLatch | DoIO deriving (Eq,Show,Ord,Enum)
+
+data Pulse a = Pulse
+    { addHandlerP :: ((Unique, Priority), Handler) -> Build ()
+    , evalP       :: EvalP (Maybe a)
+    }
+
+instance Hashable Priority where hashWithSalt _ = fromEnum
+
+data Latch a = Latch { readL :: EvalL a }
+
+{-----------------------------------------------------------------------------
+    Monads
+------------------------------------------------------------------------------}
+-- | The 'EvalP' monad is used to evaluate pulses.
+type EvalP = RWST () () Values BuildIO
+    -- state: current pulse values
+
+-- | The 'EvalL' monad is used to evaluate latches.
+type EvalL = IO
+
+-- | The 'Build' monad is used to add pulses and latches to the graph.
+type Build   = IO
+type BuildIO = Build
diff --git a/src/UseWords.hs b/src/UseWords.hs
deleted file mode 100644
--- a/src/UseWords.hs
+++ /dev/null
@@ -1,109 +0,0 @@
-{-# LANGUAGE CPP, PackageImports #-}
-{-# LANGUAGE ViewPatterns #-}
-
-module Main where
-
-import Control.Applicative hiding ((<|>),many)
-import Control.Monad
-import Control.Arrow (second)
-import Data.Maybe
-import Text.Parsec
-
-#ifdef CABAL
-import qualified  "threepenny-gui" Graphics.UI.Threepenny as UI
-import "threepenny-gui" Graphics.UI.Threepenny.Core hiding (string, (<|>), many)
-#else
-import qualified Graphics.UI.Threepenny as UI
-import Graphics.UI.Threepenny.Core hiding (string, (<|>), many)
-#endif
-import Paths
-import System.FilePath ((</>))
-
-{-----------------------------------------------------------------------------
-    GUI
-------------------------------------------------------------------------------}
-main :: IO ()
-main = do
-    static <- getStaticDir
-    startGUI defaultConfig
-        { tpPort       = 10000
-        , tpStatic     = Just static
-        } setup
-
-
-setup :: Window -> IO ()
-setup w = do
-    filename <- fmap (</> "and-then-haskell.txt") getStaticDir 
-    andthen  <- readFile filename
-    case parts filename andthen of
-        Left parseerror -> debug w $ show parseerror
-        Right parts     -> void $ do
-            UI.addStyleSheet w "use-words.css"
-
-            let (header, Prelude.drop 2 -> rest) = splitAt 3 parts            
-            
-            (views1, vars1) <- renderParts header
-            (views2, vars2) <- renderParts rest
-            varChoices      <- mapM (renderVarChoice (vars1 ++ vars2)) vars
-        
-            getBody w #+
-                [ viewSource
-                , UI.div #. "wrap" #+ (
-                    [ UI.div #. "header" #+ map element views1
-                    , UI.ul  #. "vars"   #+ map element varChoices
-                    ]
-                    ++ map element views2 )
-                ]
-            
-type VariableViews = [(Name, Element)]
-
-renderVarChoice :: VariableViews -> Variable -> IO Element
-renderVarChoice views (label,(name,def)) = do
-    input <- UI.input #. "var-value" # set value def
-    
-    on (domEvent "livechange") input $ \(EventData xs) -> do
-        let s = concat $ catMaybes xs
-        forM_ (filter ((==name).fst) views) $ \(_,el) -> do
-            element el # set text s
-    
-    UI.li #+ [UI.string (label ++ ":"), element input]
-
-renderParts :: [Part] -> IO ([Element], VariableViews)
-renderParts parts = do
-    views <- mapM renderPart parts
-    let variables = [(var, view) | (Ref var, view) <- zip parts views]
-    return (views, variables)
-
-renderPart :: Part -> IO Element
-renderPart (Text str) = UI.div #. "text" #+ [UI.string str]
-renderPart (Ref  var) = UI.div #. "var"
-    # maybe (set text $ "{" ++ var ++ "}") (either (set html) (set text))
-            (lookup var templatevars)
-
-viewSource :: IO Element
-viewSource = UI.p #+
-    [UI.anchor #. "view-source" # set UI.href url #+ [UI.string "View source code"]]
-    where
-    url = "https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/UseWords.hs"
-
-{-----------------------------------------------------------------------------
-    Parsing
-------------------------------------------------------------------------------}
-type Name     = String
-type Variable = (String, (Name, String))
-
-templatevars = map (second Right . snd) vars ++ map (second Left) exts
-
-vars :: [Variable]
-vars = [("Favourite technology",("favourite-language","Haskell"))
-       ,("Technology used at work",("work-language","Python"))
-       ,("Cool forum",("bar","LtU"))
-       ,("Particular to technology",("particular-stuff","monads"))]
-exts = [("br","<br><br>")]
-
-data Part = Text String | Ref String deriving Show
-
-parts :: SourceName -> String -> Either ParseError [Part]
-parts = parse (many (ref <|> text)) where
-    text = Text <$> many1 (notFollowedBy (string "{") *> anyChar)
-    ref  = Ref  <$> (string "{" *> many1 (noneOf "}") <* (string "}"))
diff --git a/threepenny-gui.cabal b/threepenny-gui.cabal
--- a/threepenny-gui.cabal
+++ b/threepenny-gui.cabal
@@ -1,5 +1,5 @@
 Name:                threepenny-gui
-Version:             0.3.0.1
+Version:             0.4.0.0
 Synopsis:            GUI framework that uses the web browser as a display.
 Description:
     Threepenny-GUI is a GUI framework that uses the web browser as a display.
@@ -18,25 +18,19 @@
     To build and install the example, use the @buildExamples@ flag like this
     .
     @cabal install threepenny-gui -fbuildExamples@
-    .
-    Changelog:
-    .
-    * 0.3.0.0 - Snapshot release. Browser communication with WebSockets. First stab at FRP integration.
-    .
-    * 0.2.0.0 - Snapshot release. First stab at easy JavaScript FFI.
-    .
-    * 0.1.0.0 - Initial release.
 
 License:             BSD3
 License-file:        LICENSE
 Author:              Chris Done, Heinrich Apfelmus
 Maintainer:          Heinrich Apfelmus <apfelmus at quantentunnel dot de>
 Homepage:            http://www.haskell.org/haskellwiki/Threepenny-gui
+bug-reports:         https://github.com/HeinrichApfelmus/threepenny-gui/issues
 Category:            Web, GUI
 Build-type:          Simple
 Cabal-version:       >=1.8
 
-Extra-Source-Files:  src/Graphics/UI/*.html
+Extra-Source-Files:  CHANGELOG.md
+                    ,src/Graphics/UI/*.html
                     ,src/Graphics/UI/*.js
                     ,src/Graphics/UI/*.css
 
@@ -52,16 +46,22 @@
     description: Build example executables.
     default:     False
 
+flag rebug
+    description: The library uses some techniques that are highly
+                 non-deterministic, for example garbage collection and concurrency.
+                 Bugs in these subsystems are harder to find.
+                 Activating this flag will expose more of them.
+    default:     False
+
 Source-repository head
     type:               git
     location:           git://github.com/HeinrichApfelmus/threepenny-gui.git
 
 
 Library
-  Hs-source-dirs:    src
-  Exposed-modules:
-                     Reactive.Threepenny
-                    ,Graphics.UI.Threepenny
+  hs-source-dirs:    src
+  exposed-modules:
+                     Graphics.UI.Threepenny
                     ,Graphics.UI.Threepenny.Attributes
                     ,Graphics.UI.Threepenny.Core
                     ,Graphics.UI.Threepenny.Canvas
@@ -70,40 +70,51 @@
                     ,Graphics.UI.Threepenny.Events
                     ,Graphics.UI.Threepenny.JQuery
                     ,Graphics.UI.Threepenny.Timer
-  Other-modules:
+                    ,Graphics.UI.Threepenny.Widgets
+                    ,Reactive.Threepenny
+                    ,Foreign.Coupon
+  other-modules:
                      Control.Concurrent.Chan.Extra
                     ,Control.Concurrent.Delay
-                    ,Graphics.UI.Threepenny.Internal.Core
-                    ,Graphics.UI.Threepenny.Internal.Resources
+                    ,Graphics.UI.Threepenny.Internal.Driver
+                    ,Graphics.UI.Threepenny.Internal.FFI
                     ,Graphics.UI.Threepenny.Internal.Include
+                    ,Graphics.UI.Threepenny.Internal.Resources
                     ,Graphics.UI.Threepenny.Internal.Types
-                    ,Reactive.Threepenny.PulseLatch
                     ,Reactive.Threepenny.Memo
+                    ,Reactive.Threepenny.Monads
+                    ,Reactive.Threepenny.PulseLatch
+                    ,Reactive.Threepenny.Types
                     ,Paths_threepenny_gui
-  CPP-Options:      -DCABAL
-  Build-depends:     base                      >= 4     && < 5
-                    ,snap-server
-                    ,snap-core
-                    ,websockets == 0.7.*
-                    ,websockets-snap == 0.7.*
-                    ,text
-                    ,safe
-                    ,containers
-                    ,unordered-containers
-                    ,hashable
-                    ,vault == 0.3.*
-                    ,bytestring
-                    ,json >= 0.4.4 && < 0.6
-                    ,time
-                    ,utf8-string
-                    ,network
-                    ,filepath
-                    ,data-default
-                    ,template-haskell
-                    ,transformers
-                    ,stm
-                    ,attoparsec-enumerator
-                    ,MonadCatchIO-transformers
+  extensions:        CPP
+  cpp-options:      -DCABAL
+  if flag(rebug)
+      cpp-options:  -DREBUG
+      ghc-options:  -O2   
+  build-depends:     base                   >= 4     && < 5
+                    ,attoparsec-enumerator  == 0.3.*
+                    ,bytestring             >= 0.9.2 && < 0.11
+                    ,containers             >= 0.4.2 && < 0.6
+                    ,data-default           == 0.5.*
+                    ,deepseq                == 1.3.*
+                    ,filepath               == 1.3.*
+                    ,hashable               >= 1.1.0  && < 1.3
+                    ,json                   >= 0.4.4  && < 0.6
+                    ,MonadCatchIO-transformers == 0.3.*
+                    ,network                >= 2.3.0  && < 2.5
+                    ,safe                   == 0.3.*
+                    ,snap-server            == 0.9.*
+                    ,snap-core              == 0.9.*
+                    ,stm                    >= 2.3    && < 2.5
+                    ,template-haskell       >= 2.7.0  && < 2.9
+                    ,text                   == 0.11.*
+                    ,time                   == 1.4.*
+                    ,transformers           == 0.3.*
+                    ,unordered-containers   == 0.2.*
+                    ,utf8-string            == 0.3.*
+                    ,websockets             == 0.8.*
+                    ,websockets-snap        == 0.8.*
+                    ,vault                  == 0.3.*
                     
 Executable threepenny-examples-bartab
     if flag(buildExamples)
@@ -115,7 +126,7 @@
         buildable: False
     main-is:           BarTab.hs
     other-modules:     Paths_threepenny_gui, Paths
-    hs-source-dirs:    src
+    hs-source-dirs:    samples
 
 Executable threepenny-examples-buttons
     if flag(buildExamples)
@@ -127,8 +138,34 @@
         buildable: False
     main-is:           Buttons.hs
     other-modules:     Paths_threepenny_gui, Paths
-    hs-source-dirs:    src
+    hs-source-dirs:    samples
 
+Executable threepenny-examples-chat
+    if flag(buildExamples)
+        cpp-options:       -DCABAL
+        build-depends:     base                      >= 4     && < 5
+                          ,threepenny-gui
+                          ,transformers
+                          ,filepath
+                          ,time
+    else
+        buildable: False
+    main-is:           Chat.hs
+    other-modules:     Paths_threepenny_gui, Paths, Data.List.Extra
+    hs-source-dirs:    samples
+
+Executable threepenny-examples-crud
+    if flag(buildExamples)
+        cpp-options:       -DCABAL
+        build-depends:     base                      >= 4     && < 5
+                          ,containers
+                          ,threepenny-gui
+    else
+        buildable: False
+    main-is:           CRUD.hs
+    other-modules:     Tidings
+    hs-source-dirs:    samples
+
 Executable threepenny-examples-currencyconverter
     if flag(buildExamples)
         cpp-options:       -DCABAL
@@ -138,7 +175,7 @@
     else
         buildable: False
     main-is:           CurrencyConverter.hs
-    hs-source-dirs:    src
+    hs-source-dirs:    samples
 
 Executable threepenny-examples-dragndropexample
     if flag(buildExamples)
@@ -150,7 +187,7 @@
         buildable: False
     main-is:           DragNDropExample.hs
     other-modules:     Paths_threepenny_gui, Paths
-    hs-source-dirs:    src
+    hs-source-dirs:    samples
 
 Executable threepenny-examples-drummachine
     if flag(buildExamples)
@@ -162,7 +199,7 @@
         buildable: False
     main-is:           DrumMachine.hs
     other-modules:     Paths_threepenny_gui, Paths
-    hs-source-dirs:    src
+    hs-source-dirs:    samples
 
 Executable threepenny-examples-missing-dollars
     if flag(buildExamples)
@@ -175,7 +212,7 @@
         buildable: False
     main-is:           MissingDollars.hs
     other-modules:     Paths_threepenny_gui, Paths
-    hs-source-dirs:    src
+    hs-source-dirs:    samples
 
 Executable threepenny-examples-use-words
     if flag(buildExamples)
@@ -188,18 +225,4 @@
         buildable: False
     main-is:           UseWords.hs
     other-modules:     Paths_threepenny_gui, Paths
-    hs-source-dirs:    src
-
-Executable threepenny-examples-chat
-    if flag(buildExamples)
-        cpp-options:       -DCABAL
-        build-depends:     base                      >= 4     && < 5
-                          ,threepenny-gui
-                          ,transformers
-                          ,filepath
-                          ,time
-    else
-        buildable: False
-    main-is:           Chat.hs
-    other-modules:     Paths_threepenny_gui, Paths, Data.List.Extra
-    hs-source-dirs:    src
+    hs-source-dirs:    samples
