diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2012, Adam Bergmark
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Adam Bergmark nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/fay-dom.cabal b/fay-dom.cabal
new file mode 100644
--- /dev/null
+++ b/fay-dom.cabal
@@ -0,0 +1,19 @@
+name:                fay-dom
+version:             0.2.0.0
+synopsis:            DOM FFI wrapper library for Fay
+description:         DOM FFI wrapper library for Fay.
+homepage:            https://github.com/faylang/fay-dom
+bug-reports:         https://github.com/faylang/fay-dom/issues
+license:             BSD3
+license-file:        LICENSE
+author:              Adam Bergmark
+maintainer:          Adam Bergmark
+build-type:          Simple
+cabal-version:       >=1.8
+data-files:          src/DOM.hs
+
+library
+  hs-source-dirs: src
+  exposed-modules: DOM
+  ghc-options: -Wall
+  build-depends: fay-base >= 0.14.1.0
diff --git a/src/DOM.hs b/src/DOM.hs
new file mode 100644
--- /dev/null
+++ b/src/DOM.hs
@@ -0,0 +1,102 @@
+{-# LANGUAGE EmptyDataDecls    #-}
+
+-- | Document object model functions. Most of this doesn't have
+-- anything to do with the DOM and is actually ECMA library stuff, but
+-- I'll leave it in for now.
+
+module DOM where
+
+import FFI
+import Prelude
+
+--------------------------------------------------------------------------------
+-- Foreign Data Declarations.
+
+data Document
+data Element
+data Event
+data Global
+data NodeList
+data Timer
+data XMLHttpRequest
+
+--------------------------------------------------------------------------------
+-- Browser globals
+
+getWindow :: Fay Global
+getWindow = ffi "window"
+
+getDocument :: Fay Document
+getDocument = ffi "window.document"
+
+addEvent :: String -> Fay f -> Fay ()
+addEvent = ffi "window['addEventListener'](%1,%2)"
+
+--------------------------------------------------------------------------------
+-- Events.
+
+stopProp :: Event -> Fay ()
+stopProp = ffi "%1['stopPropagation']()"
+
+preventDefault :: Event -> Fay ()
+preventDefault = ffi "%1['preventDefault']()"
+
+--------------------------------------------------------------------------------
+-- Element accessors.
+
+createElement :: String -> Fay Element
+createElement = ffi "window['document']['createElement'](%1)"
+
+appendChild :: Element -> Element -> Fay ()
+appendChild = ffi "%1.appendChild(%2)"
+
+removeChild :: Element -> Element -> Fay ()
+removeChild = ffi "%1.removeChild(%2)"
+
+parentNode :: Element -> Fay Element
+parentNode = ffi "%1.parentNode"
+
+children :: Element -> Fay NodeList
+children = ffi "%1.children"
+
+--------------------------------------------------------------------------------
+-- Timers
+
+-- | setInterval except the calling function gets the timer as an
+-- | argument so the interval can be cancelled from within it.
+setInterval :: Double -> (Timer -> Fay ()) -> Fay Timer
+setInterval = ffi "(function (f,i) { var id = window['setInterval'](function () { f(id); }, i); })(%2,%1)"
+
+clearInterval :: Timer -> Fay ()
+clearInterval = ffi "window['clearInterval'](%1)"
+
+setTimeout :: Double -> (Timer -> Fay ()) -> Fay Timer
+setTimeout = ffi "window['setTimeout'](%2,%1)"
+
+--------------------------------------------------------------------------------
+-- XMLHttpRequest
+
+data RequestMethod = GET | POST | PUT | HEAD
+
+data ReadyState = UNSENT | OPENED | HEADERS_RECEIVED | LOADING | DONE
+
+xmlHttpRequest :: Fay XMLHttpRequest
+xmlHttpRequest = ffi "(function(window) { if(window['XMLHttpRequest']) return new XMLHttpRequest(); else return new ActiveXObject('Microsoft.XMLHTTP'); })(window)"
+
+open :: RequestMethod -> String -> XMLHttpRequest -> Fay XMLHttpRequest
+open = ffi "(function(method, url, xhr) { xhr['open'](method['instance'], url, true); return xhr; })(%1, %2, %3)"
+
+send :: XMLHttpRequest -> Fay ()
+send = ffi "%1['send']()"
+
+setReadyStateHandler :: (XMLHttpRequest -> Fay ()) -> XMLHttpRequest -> Fay XMLHttpRequest
+setReadyStateHandler = ffi "(function(handler, xhr) { xhr['onreadystatechange'] = function() { handler(xhr); }; return xhr; })(%1, %2)"
+
+readyState :: XMLHttpRequest -> Fay ReadyState
+readyState = ffi "{ instance: ['UNSENT', 'OPENED', 'HEADERS_RECEIVED', 'LOADING', 'DONE'][%1['readyState']] }"
+
+responseText :: XMLHttpRequest -> Fay String
+responseText = ffi "%1['responseText']"
+
+status :: XMLHttpRequest -> Fay Int
+status = ffi "%1['status']"
