diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,30 @@
+## 0.1.0
+
+* Injection has been moved to a submodule, "Data.FileEmbed.Inject".
+* The ByteString-centric API has been shifted over to one that can produce any member of the IsString typeclass.
+    * Correspondingly, the `embedString*` API has been removed, as it is now redundant.
+*  Several generally-unused internal functions are no longer exported.
+
+## 0.0.10
+
+* `makeRelativeToProject`
+
+## 0.0.9
+
+* embedStringFile [#14](https://github.com/snoyberg/file-embed/pull/14)
+
+## 0.0.8.2
+
+* Improve inject documentation [#11](https://github.com/snoyberg/file-embed/issues/11)
+
+## 0.0.8.1
+
+Minor cleanup
+
+## 0.0.8
+
+* Custom postfix for magic string [#7](https://github.com/snoyberg/file-embed/issues/7)
+
+## 0.0.7.1
+
+Minor cleanup
diff --git a/Data/FileEmbed.hs b/Data/FileEmbed.hs
new file mode 100644
--- /dev/null
+++ b/Data/FileEmbed.hs
@@ -0,0 +1,159 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE TemplateHaskell #-}
+-- | This module uses template Haskell. Following is a simplified explanation of usage for those unfamiliar with calling Template Haskell functions.
+--
+-- The function @embedFile@ in this modules embeds a file into the executable
+-- that you can use it at runtime. A file is represented as a @ByteString@.
+-- However, as you can see below, the type signature indicates a value of type
+-- @Q Exp@ will be returned. In order to convert this into a @ByteString@, you
+-- must use Template Haskell syntax, e.g.:
+--
+-- > $(embedFile "myfile.txt")
+--
+-- This expression will have type @ByteString@. Be certain to enable the
+-- TemplateHaskell language extension, usually by adding the following to the
+-- top of your module:
+--
+-- > {-# LANGUAGE TemplateHaskell #-}
+module Data.FileEmbed
+    ( -- * Embed at compile time
+      embedFile
+    , embedOneFileOf
+    , embedDir
+      -- * Relative path manipulation
+    , makeRelativeToProject
+    ) where
+
+import Language.Haskell.TH.Syntax
+    ( Exp (AppE, ListE, LitE, TupE, SigE, VarE)
+    , Lit (StringL)
+    , Q
+    , runIO
+    , qLocation, loc_filename
+#if MIN_VERSION_template_haskell(2, 7, 0)
+    , Quasi(qAddDependentFile)
+#endif
+    )
+import System.Directory (doesDirectoryExist, doesFileExist,
+                         getDirectoryContents, canonicalizePath)
+import Control.Applicative ((<|>), (<$>))
+import Control.Exception (throw, ErrorCall(..))
+import Control.Monad (filterM)
+import Control.Arrow ((&&&), second)
+import System.FilePath ((</>), takeDirectory, takeExtension)
+import Data.String (IsString, fromString)
+import Prelude as P
+
+
+-- | Embed a single file in your source code.
+--
+-- > import Data.String
+-- >
+-- > myFile :: IsString a => a
+-- > myFile = $(embedFile "dirName/fileName")
+embedFile :: FilePath -> Q Exp
+embedFile fp =
+#if MIN_VERSION_template_haskell(2, 7, 0)
+    qAddDependentFile fp >>
+#endif
+  (runIO $ readFile fp) >>= toExp
+
+-- | Embed a single existing string file in your source code
+-- out of list a list of paths supplied.
+embedOneFileOf :: [FilePath] -> Q Exp
+embedOneFileOf  ps =
+  (runIO $ readExistingFile ps) >>= \ ( path, content ) -> do
+#if MIN_VERSION_template_haskell(2, 7, 0)
+    qAddDependentFile path
+#endif
+    toExp content
+  where
+    readExistingFile :: [FilePath] -> IO (FilePath, String)
+    readExistingFile xs = do
+      ys <- filterM doesFileExist xs
+      case ys of
+        (p:_) -> readFile p >>= \ c -> return ( p, c )
+        _ -> throw $ ErrorCall "Cannot find file to embed as resource"
+
+-- | Embed a directory recursively in your source code.
+--
+-- > import Data.String
+-- >
+-- > myDir :: IsString a => [(FilePath, a)]
+-- > myDir = $(embedDir "dirName")
+embedDir :: FilePath -> Q Exp
+embedDir fp = do
+    typ <- [t| forall a. IsString a => [(FilePath, a)] |]
+    e <- ListE <$> ((runIO $ getDir) >>= mapM (pairToExp fp))
+    return $ SigE e typ
+    where 
+        getDir = fileList fp ""
+
+        pairToExp :: FilePath -> (FilePath, String) -> Q Exp
+        pairToExp _root (path, bs) = do
+#if MIN_VERSION_template_haskell(2, 7, 0)
+            qAddDependentFile $ _root ++ '/' : path
+#endif
+            exp' <- toExp bs
+            return $! TupE [LitE $ StringL path, exp']
+
+fileList :: FilePath -> FilePath -> IO [(FilePath, String)]
+fileList realTop top = do
+    allContents <- filter notHidden <$> getDirectoryContents (realTop </> top)
+    let all' = map ((top </>) &&& (\x -> realTop </> top </> x)) allContents
+    files <- filterM (doesFileExist . snd) all' >>=
+             mapM (liftPair2 . second readFile)
+    dirs <- filterM (doesDirectoryExist . snd) all' >>=
+            mapM (fileList realTop . fst)
+    return $ concat $ files : dirs
+    where
+        notHidden :: FilePath -> Bool
+        notHidden ('.':_) = False
+        notHidden _ = True
+
+        liftPair2 :: Monad m => (a, m b) -> m (a, b)
+        liftPair2 (a, b) = b >>= \b' -> return (a, b')
+
+toExp :: String -> Q Exp
+toExp s =
+    return $ VarE 'fromString
+      `AppE` LitE (StringL s)
+
+-- | Take a relative file path and attach it to the root of the current
+-- project.
+--
+-- The idea here is that, when building with Stack, the build will always be
+-- executed with a current working directory of the root of the project (where
+-- your .cabal file is located). However, if you load up multiple projects with
+-- @stack ghci@, the working directory may be something else entirely.
+--
+-- This function looks at the source location of the Haskell file calling it,
+-- finds the first parent directory with a .cabal file, and uses that as the
+-- root directory for fixing the relative path.
+--
+-- > $(makeRelativeToProject "data/foo.txt" >>= embedFile)
+--
+-- @since 0.0.10
+makeRelativeToProject :: FilePath -> Q FilePath
+makeRelativeToProject rel = do
+    loc <- qLocation
+    runIO $ do
+        srcFP <- canonicalizePath $ loc_filename loc
+        mdir <- findProjectDir srcFP
+        case mdir of
+            Nothing -> error $ "Could not find .cabal file for path: " ++ srcFP
+            Just dir -> return $ dir </> rel
+  where
+    findProjectDir x = do
+        let dir = takeDirectory x
+        if dir == x
+            then return Nothing
+            else do
+                contents <- getDirectoryContents dir
+                if any isCabalFile contents
+                    then return (Just dir)
+                    else findProjectDir dir
+
+    isCabalFile fp = takeExtension fp == ".cabal"
diff --git a/Data/FileEmbed/Inject.hs b/Data/FileEmbed/Inject.hs
new file mode 100644
--- /dev/null
+++ b/Data/FileEmbed/Inject.hs
@@ -0,0 +1,141 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TemplateHaskell #-}
+
+module Data.FileEmbed.Inject (
+    -- * Inject into an executable
+    -- $inject
+      dummySpace
+    , dummySpaceWith
+    , inject
+    , injectFile
+    , injectWith
+    , injectFileWith
+    ) where
+
+import Language.Haskell.TH.Syntax (Exp (LitE), Lit (StringPrimL), Q)
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Char8 as B8
+import Data.ByteString.Unsafe (unsafePackAddressLen)
+import System.IO.Unsafe (unsafePerformIO)
+import Prelude as P
+
+magic :: B.ByteString -> B.ByteString
+magic x = B8.concat ["fe", x]
+
+sizeLen :: Int
+sizeLen = 20
+
+getInner :: B.ByteString -> B.ByteString
+getInner b =
+    let (sizeBS, rest) = B.splitAt sizeLen b
+     in case reads $ B8.unpack sizeBS of
+            (i, _):_ -> B.take i rest
+            [] -> error "Data.FileEmbed (getInner): Your dummy space has been corrupted."
+
+padSize :: Int -> String
+padSize i =
+    let s = show i
+     in replicate (sizeLen - length s) '0' ++ s
+
+-- | Allocate the given number of bytes in the generate executable. That space
+-- can be filled up with the 'inject' and 'injectFile' functions.
+dummySpace :: Int -> Q Exp
+dummySpace = dummySpaceWith "MS"
+
+-- | Like 'dummySpace', but takes a postfix for the magic string.  In
+-- order for this to work, the same postfix must be used by 'inject' /
+-- 'injectFile'.  This allows an executable to have multiple
+-- 'ByteString's injected into it, without encountering collisions.
+--
+-- Since 0.0.8
+dummySpaceWith :: B.ByteString -> Int -> Q Exp
+dummySpaceWith postfix space = do
+    let size = padSize space
+        magic' = magic postfix
+        start = B8.unpack magic' ++ size
+        magicLen = B8.length magic'
+        len = magicLen + sizeLen + space
+        chars = LitE $ StringPrimL $
+#if MIN_VERSION_template_haskell(2, 6, 0)
+            map (toEnum . fromEnum) $
+#endif
+            start ++ replicate space '0'
+    [| getInner (B.drop magicLen (unsafePerformIO (unsafePackAddressLen len $(return chars)))) |]
+
+-- | Inject some raw data inside a @ByteString@ containing empty, dummy space
+-- (allocated with @dummySpace@). Typically, the original @ByteString@ is an
+-- executable read from the filesystem.
+inject :: B.ByteString -- ^ bs to inject
+       -> B.ByteString -- ^ original BS containing dummy
+       -> Maybe B.ByteString -- ^ new BS, or Nothing if there is insufficient dummy space
+inject = injectWith "MS"
+
+-- | Like 'inject', but takes a postfix for the magic string.
+--
+-- Since 0.0.8
+injectWith :: B.ByteString -- ^ postfix of magic string
+           -> B.ByteString -- ^ bs to inject
+           -> B.ByteString -- ^ original BS containing dummy
+           -> Maybe B.ByteString -- ^ new BS, or Nothing if there is insufficient dummy space
+injectWith postfix toInj orig =
+    if toInjL > size
+        then Nothing
+        else Just $ B.concat [before, magic', B8.pack $ padSize toInjL, toInj, B8.pack $ replicate (size - toInjL) '0', after]
+  where
+    magic' = magic postfix
+    toInjL = B.length toInj
+    (before, rest) = B.breakSubstring magic' orig
+    (sizeBS, rest') = B.splitAt sizeLen $ B.drop (B8.length magic') rest
+    size = case reads $ B8.unpack sizeBS of
+            (i, _):_ -> i
+            [] -> error $ "Data.FileEmbed (inject): Your dummy space has been corrupted. Size is: " ++ show sizeBS
+    after = B.drop size rest'
+
+-- | Same as 'inject', but instead of performing the injecting in memory, read
+-- the contents from the filesystem and write back to a different file on the
+-- filesystem.
+injectFile :: B.ByteString -- ^ bs to inject
+           -> FilePath -- ^ template file
+           -> FilePath -- ^ output file
+           -> IO ()
+injectFile = injectFileWith "MS"
+
+-- | Like 'injectFile', but takes a postfix for the magic string.
+--
+-- Since 0.0.8
+injectFileWith :: B.ByteString -- ^ postfix of magic string
+               -> B.ByteString -- ^ bs to inject
+               -> FilePath -- ^ template file
+               -> FilePath -- ^ output file
+               -> IO ()
+injectFileWith postfix inj srcFP dstFP = do
+    src <- B.readFile srcFP
+    case injectWith postfix inj src of
+        Nothing -> error "Insufficient dummy space"
+        Just dst -> B.writeFile dstFP dst
+
+{- $inject
+
+The inject system allows arbitrary content to be embedded inside a Haskell
+executable, post compilation. Typically, file-embed allows you to read some
+contents from the file system at compile time and embed them inside your
+executable. Consider a case, instead, where you would want to embed these
+contents after compilation. Two real-world examples are:
+
+* You would like to embed a hash of the executable itself, for sanity checking in a network protocol. (Obviously the hash will change after you embed the hash.)
+
+* You want to create a self-contained web server that has a set of content, but will need to update the content on machines that do not have access to GHC.
+
+The typical workflow use:
+
+* Use 'dummySpace' or 'dummySpaceWith' to create some empty space in your executable
+
+* Use 'injectFile' or 'injectFileWith' from a separate utility to modify that executable to have the updated content.
+
+The reason for the @With@-variant of the functions is for cases where you wish
+to inject multiple different kinds of content, and therefore need control over
+the magic key. If you know for certain that there will only be one dummy space
+available, you can use the non-@With@ variants.
+
+-}
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,25 @@
+The following license covers this documentation, and the source code, except
+where otherwise indicated.
+
+Copyright 2008, Michael Snoyman. 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.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "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 HOLDERS 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/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,4 @@
+## file-embed
+
+Use Template Haskell to read a file or all the files in a directory, and turn
+them into (path, bytestring) pairs embedded in your haskell code.
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,7 @@
+#!/usr/bin/env runhaskell
+
+> module Main where
+> import Distribution.Simple
+
+> main :: IO ()
+> main = defaultMain
diff --git a/file-embed-poly.cabal b/file-embed-poly.cabal
new file mode 100644
--- /dev/null
+++ b/file-embed-poly.cabal
@@ -0,0 +1,53 @@
+name:            file-embed-poly
+version:         0.1.0
+license:         BSD3
+license-file:    LICENSE
+author:          Michael Snoyman <michael@snoyman.com>, Alexis Williams <sasinestro@gmail.com>
+maintainer:      Alexis Williams <sasinestro@gmail.com>
+synopsis:        Use Template Haskell to embed file contents directly.
+description:     Use Template Haskell to read a file or all the files in a
+                 directory, and turn them into (path, IsString) pairs
+                 embedded in your haskell code.
+
+                 This is a (hopefully temporary) fork of the original file-embed by Micheal Snoyman.
+category:        Data
+stability:       Stable
+cabal-version:   >= 1.8
+build-type:      Simple
+homepage:        https://github.com/sasinestro/file-embed
+extra-source-files: test/injection-test/*.hs
+                  , test/sample/.hidden, test/sample/bar, test/sample/baz, test/sample/bin, test/sample/binary
+                  , ChangeLog.md
+                    README.md
+
+flag test-injection
+    description: Builds the test that ensures that embedded file injection works. It's mostly seperate and it pulls in more dependencies.
+    default: False
+
+library
+    build-depends:   base               >= 4       && < 5
+                   , bytestring         >= 0.9.1.4
+                   , directory          >= 1.0.0.3
+                   , template-haskell   >= 2.5.0.0
+                   , filepath
+    exposed-modules: Data.FileEmbed
+                   , Data.FileEmbed.Inject
+    ghc-options:     -Wall
+
+test-suite test
+    type: exitcode-stdio-1.0
+    main-is: main.hs
+    hs-source-dirs: test
+    build-depends: base
+                 , bytestring
+                 , directory
+                 , file-embed
+                 , filepath
+                 , hspec                >= 2.1
+    if flag(test-injection)
+        build-depends: shelly           >= 1.6.1
+        cpp-options: -DTEST_INJECTION
+
+source-repository head
+  type:     git
+  location: https://github.com/sasinestro/file-embed
diff --git a/test/injection-test/inject.hs b/test/injection-test/inject.hs
new file mode 100644
--- /dev/null
+++ b/test/injection-test/inject.hs
@@ -0,0 +1,4 @@
+{-# LANGUAGE OverloadedStrings #-}
+import Data.FileEmbed.Inject
+
+main = injectFile "Hello World" "template" "injected"
diff --git a/test/injection-test/template.hs b/test/injection-test/template.hs
new file mode 100644
--- /dev/null
+++ b/test/injection-test/template.hs
@@ -0,0 +1,4 @@
+{-# LANGUAGE TemplateHaskell #-}
+import Data.FileEmbed.Inject
+
+main = print $(dummySpace 100)
diff --git a/test/main.hs b/test/main.hs
new file mode 100644
--- /dev/null
+++ b/test/main.hs
@@ -0,0 +1,69 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TemplateHaskell   #-}
+
+module Main (main) where
+
+import Test.Hspec
+
+#ifdef TEST_INJECTION
+import Shelly (shelly, silently, run, run_, findWhen, hasExt, toTextIgnore, pwd, chdir, get_env_text, setenv, appendToPath) 
+#endif 
+
+import Control.Applicative ((<$>))
+import Control.Arrow ((&&&), second)
+import Control.Monad (filterM, mapM)
+import Data.FileEmbed
+import qualified Data.ByteString as B
+import System.Directory (doesDirectoryExist, doesFileExist, getDirectoryContents)
+import System.FilePath ((</>))
+
+getDir :: FilePath -> IO [(FilePath, B.ByteString)]
+getDir top = getDir' top ""
+    where
+        notHidden :: FilePath -> Bool
+        notHidden ('.':_) = False
+        notHidden _ = True
+
+        liftPair2 :: Monad m => (a, m b) -> m (a, b)
+        liftPair2 (a, b) = b >>= \b' -> return (a, b')
+
+        getDir' :: FilePath -> FilePath -> IO [(FilePath, B.ByteString)]
+        getDir' realTop top = do
+            allContents <- filter notHidden <$> getDirectoryContents (realTop </> top)
+            let all' = map ((top </>) &&& (\x -> realTop </> top </> x)) allContents
+            files <- filterM (doesFileExist . snd) all' >>=
+                    mapM (liftPair2 . second B.readFile)
+            dirs <- filterM (doesDirectoryExist . snd) all' >>=
+                    mapM (getDir' realTop . fst)
+            return $ concat $ files : dirs
+
+shouldReturn' :: (Show a, Eq a) => a -> IO a -> Expectation
+shouldReturn' = flip shouldReturn
+
+main :: IO ()
+main = hspec . describe "Data.FileEmbed" $ do
+    describe "embedFile" $ do
+        it "handles text files" $ ($(embedFile "test/sample/bar") :: B.ByteString) `shouldReturn'` B.readFile "test/sample/bar"
+        it "handles binary files" $ ($(embedFile "test/sample/binary") :: B.ByteString) `shouldReturn'` B.readFile "test/sample/binary"
+        
+    describe "embedDir" $ do
+        let sampleDir = $(embedDir "test/sample") :: [(FilePath, B.ByteString)]
+        correct <- runIO $ Main.getDir "test/sample"
+        it "handles text and binary files" $ sampleDir `shouldBe` correct
+#ifdef TEST_INJECTION
+    describe "Data.FileEmbed.Inject" $ do
+        it "correctly injects data into a binary" $ (shelly . chdir "test/injection-test" $ do
+            path <- get_env_text "PATH"
+            appendToPath =<< pwd
+            -- Build template and run injector
+            silently $ run_ "stack" ["ghc", "--", "template.hs"]
+            run_ "stack" ["runghc", "--", "inject.hs"]
+            -- Set injected file as executable and run it
+            run_ "chmod" ["+x", "injected"]
+            out <- silently $ run "injected" []
+            -- Clean up
+            run "rm" =<< (map toTextIgnore) <$> findWhen (return . not . hasExt "hs") "."
+            setenv "PATH" path
+            return out) `shouldReturn` "\"Hello World\"\n"
+#endif
diff --git a/test/sample/.hidden b/test/sample/.hidden
new file mode 100644
--- /dev/null
+++ b/test/sample/.hidden
diff --git a/test/sample/bar b/test/sample/bar
new file mode 100644
--- /dev/null
+++ b/test/sample/bar
@@ -0,0 +1,1 @@
+bar bar bar
diff --git a/test/sample/baz b/test/sample/baz
new file mode 100644
--- /dev/null
+++ b/test/sample/baz
@@ -0,0 +1,1 @@
+baz baz baz
diff --git a/test/sample/bin b/test/sample/bin
new file mode 100644
--- /dev/null
+++ b/test/sample/bin
@@ -0,0 +1,1 @@
+bin bin bin
diff --git a/test/sample/binary b/test/sample/binary
new file mode 100644
Binary files /dev/null and b/test/sample/binary differ
