diff --git a/FB.hs b/FB.hs
new file mode 100644
--- /dev/null
+++ b/FB.hs
@@ -0,0 +1,25 @@
+module FB
+  ( getObject
+  , getUser
+  , getUserFriends
+  , Id(..), Friend(..), User(..)
+  ) where
+
+import FB.DataSource
+import Data.Aeson
+import Facebook (Id(..), Friend(..), User(..))
+
+import Haxl.Core
+
+-- | Fetch an arbitrary object in the Facebook graph.
+getObject :: Id -> GenHaxl u Object
+getObject id = dataFetch (GetObject id)
+
+-- | Fetch a Facebook user.
+getUser :: Id -> GenHaxl u User
+getUser id = dataFetch (GetUser id)
+
+-- | Fetch the friends of a Facebook user that are registered with the
+-- current app.
+getUserFriends :: Id -> GenHaxl u [Friend]
+getUserFriends id = dataFetch (GetUserFriends id)
diff --git a/FB/DataSource.hs b/FB/DataSource.hs
new file mode 100644
--- /dev/null
+++ b/FB/DataSource.hs
@@ -0,0 +1,116 @@
+{-# LANGUAGE OverloadedStrings, StandaloneDeriving, RecordWildCards,
+    GADTs, TypeFamilies, MultiParamTypeClasses, DeriveDataTypeable,
+    FlexibleInstances #-}
+-- QSem was deprecated in 7.6, but no more
+{-# OPTIONS_GHC -fno-warn-deprecations #-}
+module FB.DataSource
+  ( FacebookReq(..)
+  , initGlobalState
+  , Credentials(..)
+  , UserAccessToken
+  , AccessToken(..)
+  ) where
+
+import Network.HTTP.Conduit
+import Facebook as FB
+import Control.Monad.Trans.Resource
+import Data.Hashable
+import Data.Typeable
+import Network.HTTP.Client.TLS (tlsManagerSettings)
+import Data.Conduit
+import Data.Conduit.List hiding (mapM, mapM_)
+import Data.Monoid
+import Data.Aeson
+import Control.Concurrent.Async
+import Control.Concurrent.QSem
+import Control.Exception
+
+import Haxl.Core
+
+data FacebookReq a where
+   GetObject      :: Id -> FacebookReq Object
+   GetUser        :: UserId -> FacebookReq User
+   GetUserFriends :: UserId -> FacebookReq [Friend]
+  deriving Typeable
+
+deriving instance Eq (FacebookReq a)
+deriving instance Show (FacebookReq a)
+
+instance Show1 FacebookReq where show1 = show
+
+instance Hashable (FacebookReq a) where
+  hashWithSalt s (GetObject (Id id))      = hashWithSalt s (0::Int,id)
+  hashWithSalt s (GetUser (Id id))        = hashWithSalt s (1::Int,id)
+  hashWithSalt s (GetUserFriends (Id id)) = hashWithSalt s (2::Int,id)
+
+instance StateKey FacebookReq where
+  data State FacebookReq =
+    FacebookState
+       { credentials :: Credentials
+       , userAccessToken :: UserAccessToken
+       , manager :: Manager
+       , numThreads :: Int
+       }
+
+instance DataSourceName FacebookReq where
+  dataSourceName _ = "Facebook"
+
+instance DataSource u FacebookReq where
+  fetch = facebookFetch
+
+initGlobalState
+  :: Int
+  -> Credentials
+  -> UserAccessToken
+  -> IO (State FacebookReq)
+
+initGlobalState threads creds token = do
+  manager <- newManager tlsManagerSettings
+  return FacebookState
+    { credentials = creds
+    , manager = manager
+    , userAccessToken = token
+    , numThreads = threads
+    }
+
+facebookFetch
+  :: State FacebookReq
+  -> Flags
+  -> u
+  -> [BlockedFetch FacebookReq]
+  -> PerformFetch
+
+facebookFetch FacebookState{..} _flags _user bfs =
+  AsyncFetch $ \inner -> do
+    sem <- newQSem numThreads
+    asyncs <- mapM (fetchAsync credentials manager userAccessToken sem) bfs
+    inner
+    mapM_ wait asyncs
+
+fetchAsync
+  :: Credentials -> Manager -> UserAccessToken -> QSem
+  -> BlockedFetch FacebookReq
+  -> IO (Async ())
+fetchAsync creds manager tok sem (BlockedFetch req rvar) =
+  async $ bracket_ (waitQSem sem) (signalQSem sem) $ do
+    e <- Control.Exception.try $
+           runResourceT $ runFacebookT creds manager $ fetchReq tok req
+    case e of
+      Left ex -> putFailure rvar (ex :: SomeException)
+      Right a -> putSuccess rvar a
+
+fetchReq
+  :: UserAccessToken
+  -> FacebookReq a
+  -> FacebookT Auth (ResourceT IO) a
+
+fetchReq tok (GetObject (Id id)) =
+  getObject ("/" <> id) [] (Just tok)
+
+fetchReq _tok (GetUser id) =
+  getUser id [] Nothing
+
+fetchReq tok (GetUserFriends id) = do
+  f <- getUserFriends id [] tok
+  source <- fetchAllNextPages f
+  source $$ consume
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2014, Facebook, Inc.
+
+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 Simon Marlow 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/TestFB.hs b/TestFB.hs
new file mode 100644
--- /dev/null
+++ b/TestFB.hs
@@ -0,0 +1,84 @@
+{-# LANGUAGE RebindableSyntax, OverloadedStrings #-}
+module Main (main) where
+
+import Control.Exception as E
+import Data.Aeson
+import Data.HashMap.Strict ((!))
+import Data.Time.Calendar
+import Data.Time.Clock
+import FB
+import FB.DataSource
+import Haxl.Core
+import Haxl.Prelude
+import System.Environment
+import System.Exit
+import System.IO.Error
+import qualified Data.HashMap.Strict as HashMap
+import qualified Data.Text as T
+import qualified Data.Vector as Vector
+
+main = do
+  (creds, access_token) <- getCredentials
+  facebookState <- initGlobalState 10 creds access_token
+  env <- initEnv (stateSet facebookState stateEmpty) ()
+  r <- runHaxl env $ do
+    likes <- getObject "me/likes"
+    mapM getObject (likeIds likes)      -- these happen concurrently
+  print r
+
+likeIds :: Object -> [Id]
+likeIds likes = do
+  Array arr <- [likes ! "data"]
+  Object obj <- Vector.toList arr
+  String id <- [obj ! "id"]
+  return (Id id)
+
+-- Modifed from the test in the fb package:
+-- https://github.com/meteficha/fb/blob/master/tests/Main.hs
+-- Copyright (c)2012, Felipe Lessa
+
+-- | Grab the Facebook credentials from the environment.
+getCredentials :: IO (Credentials, UserAccessToken)
+getCredentials = tryToGet `E.catch` showHelp
+    where
+      tryToGet = do
+        [appName, appId, appSecret, accessToken] <-
+           mapM getEnv ["APP_NAME", "APP_ID", "APP_SECRET", "ACCESS_TOKEN"]
+        now <- getCurrentTime
+        let creds = Credentials (T.pack appName)
+                                (T.pack appId)
+                                (T.pack appSecret)
+            access_token = UserAccessToken
+                             (Id "me")
+                             (T.pack accessToken)
+                             now
+        return (creds, access_token)
+
+      showHelp exc | not (isDoesNotExistError exc) = E.throw exc
+      showHelp _ = do
+        putStrLn $ unlines
+          [ "In order to run the tests from the 'haxl-facebook' package, you"
+          , "need developer access to a Facebook app.  Create an app by"
+          , "going to http://developers.facebook.com, select \"Create a New"
+          , " App\" from the \"Apps\" menu at the top.  Then create an"
+          , "access token using the Graph API explorer:"
+          , "   https://developers.facebook.com/tools/explorer"
+          , "Select your app from the \"Application\" menu at the top, then hit"
+          , "\"Get Access Token\".  The access token will last about 2 hours."
+          , ""
+          , "Please supply your app's name, id and secret in the environment"
+          , "variables APP_NAME, APP_ID and APP_SECRET, respectively, and"
+          , "the access token in ACCESS_TOKEN."
+          , ""
+          , "For example, before running the test you could run in the shell:"
+          , ""
+          , " $ export APP_NAME=\"test\""
+          , " $ export APP_ID=\"000000000000000\""
+          , " $ export APP_SECRET=\"xxxxxxxxxxxxxxxxxxxxxxxxxxxx\""
+          , " $ export ACCESS_TOKEN=\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\""
+          , ""
+          , "Of course, these values above aren't valid and you need to"
+          , "replace them with your own."
+          , ""
+          , "(Exiting now with a failure code.)"]
+        exitFailure
diff --git a/haxl-facebook.cabal b/haxl-facebook.cabal
new file mode 100644
--- /dev/null
+++ b/haxl-facebook.cabal
@@ -0,0 +1,79 @@
+name:                haxl-facebook
+version:             0.1.0.0
+synopsis:            An example Haxl data source for accessing the
+                     Facebook Graph API
+homepage:            https://github.com/facebook/Haxl
+bug-reports:         https://github.com/facebook/Haxl/issues
+license:             BSD3
+license-file:        LICENSE
+author:              Facebook, Inc.
+maintainer:          The Haxl Team <haxl-team@fb.com>
+copyright:           2014 (C) 2014 Facebook, Inc.
+category:            Concurrency, Network
+build-type:          Simple
+cabal-version:       >=1.10
+
+library
+  build-depends:
+    base >=4.6 && <4.8,
+    aeson >=0.6 && <0.8,
+    fb >=1.0 && <1.1,
+    http-conduit >=2.1 && <2.2,
+    resourcet >=1.1 && <1.2,
+    text >=0.11 && <1.2,
+    transformers >=0.3 && <0.5,
+    hashable >=1.2 && <1.3,
+    data-default >=0.5 && <0.6,
+    http-client-tls >=0.2 && <0.3,
+    time >=1.4 && <1.5,
+    conduit >=1.1 && <1.2,
+    async >=2.0 && <2.1,
+    haxl == 0.1.*
+
+  other-extensions:
+    OverloadedStrings,
+    StandaloneDeriving,
+    RecordWildCards,
+    GADTs,
+    TypeFamilies,
+    MultiParamTypeClasses,
+    DeriveDataTypeable
+
+  exposed-modules:
+    FB,
+    FB.DataSource
+
+  ghc-options:
+    -Wall -fno-warn-name-shadowing
+
+  default-language:
+    Haskell2010
+
+test-suite test
+  type:
+    exitcode-stdio-1.0
+
+  main-is:
+    TestFB.hs
+
+  build-depends:
+    base >=4.6 && <4.8,
+    aeson >=0.6 && <0.8,
+    fb >=1.0 && <1.1,
+    http-conduit >=2.1 && <2.2,
+    resourcet >=1.1 && <1.2,
+    text >=0.11 && <1.2,
+    transformers >=0.3 && <0.5,
+    hashable >=1.2 && <1.3,
+    data-default >=0.5 && <0.6,
+    http-client-tls >=0.2 && <0.3,
+    time >=1.4 && <1.5,
+    conduit >=1.1 && <1.2,
+    async >=2.0 && <2.1,
+    haxl == 0.1.*,
+    unordered-containers == 0.2.*,
+    time == 1.4.*,
+    vector >= 0.10 && < 0.11
+
+  default-language:
+    Haskell2010
