diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2015, Liam O'Connor
+
+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 Liam O'Connor 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/latex-formulae-hakyll.cabal b/latex-formulae-hakyll.cabal
new file mode 100644
--- /dev/null
+++ b/latex-formulae-hakyll.cabal
@@ -0,0 +1,36 @@
+-- Initial latex-formulae-hakyll.cabal generated by cabal init.  For 
+-- further documentation, see http://haskell.org/cabal/users-guide/
+
+name:                latex-formulae-hakyll
+version:             0.1.0.0
+synopsis:            Use actual LaTeX to render formulae inside Hakyll pages
+description:         This library provides functions to render all math formulae inside Pandoc-processed Hakyll pages using
+                     real LaTeX.
+                     .
+                     It also provides a simple LRU cache to avoid recompiling the same formulae repeatedly during a @watch@
+                     session.
+homepage:            https://github.com/liamoc/latex-formulae#readme
+license:             BSD3
+license-file:        LICENSE
+author:              Liam O'Connor
+maintainer:          liamoc@cse.unsw.edu.au
+copyright:           Liam O'Connor, 2015
+category:            Image
+build-type:          Simple
+cabal-version:       >=1.10
+source-repository head
+  type:     git
+  location: https://github.com/liamoc/latex-formulae
+
+library
+  exposed-modules:     Hakyll.Contrib.LaTeX
+  -- other-modules:       
+  -- other-extensions:    
+  build-depends:       base >=4.7 && <4.9
+               ,       latex-formulae-image >= 0.1.1.0  && < 0.2  
+               ,       latex-formulae-pandoc >= 0.2.0.1 && < 0.3
+               ,       hakyll >= 4.6 && < 4.8
+               ,       pandoc-types >= 1.12 && < 1.13
+               ,       lrucache >= 1.2 && <1.3
+  hs-source-dirs:      src
+  default-language:    Haskell2010
diff --git a/src/Hakyll/Contrib/LaTeX.hs b/src/Hakyll/Contrib/LaTeX.hs
new file mode 100644
--- /dev/null
+++ b/src/Hakyll/Contrib/LaTeX.hs
@@ -0,0 +1,79 @@
+{-# LANGUAGE ViewPatterns #-}
+-- | This module provides a basic framework to render LaTeX formulae inside Pandoc documents
+--   for Hakyll pages.
+--
+--   See the latex-formulae page on GitHub for more information.
+--
+--      https://github.com/liamoc/latex-formulae#readme
+--
+module Hakyll.Contrib.LaTeX
+       ( initFormulaCompilerDataURI
+       , CacheSize
+       , compileFormulaeDataURI
+       ) where
+
+import Image.LaTeX.Render
+import Image.LaTeX.Render.Pandoc
+import Text.Pandoc.Definition
+import Hakyll.Core.Item
+import Hakyll.Core.Compiler
+import Data.Char
+import qualified Data.Cache.LRU.IO as LRU
+import Control.Applicative
+import Prelude
+
+-- | Number of formula images to keep in memory during a @watch@ session.
+type CacheSize = Integer
+
+-- | Creates a formula compiler with caching. Can be used as in the following minimal example:
+--
+-- >    main = do
+-- >       renderFormulae <- initFormulaCompilerDataURI 1000 defaultEnv
+-- >       hakyll $
+-- >         match "posts/*.markdown" $ do
+-- >           route $ setExtension "html"
+-- >           compile $ pandocCompilerWithTransformM (renderFormulae defaultPandocFormulaOptions)
+--
+initFormulaCompilerDataURI :: CacheSize -> EnvironmentOptions
+                           -> IO (PandocFormulaOptions -> Item Pandoc -> Compiler (Item Pandoc))
+initFormulaCompilerDataURI cs eo = do
+    mImageForFormula <- curry <$> memoizeLru (Just cs) (uncurry drawFormula)
+    let eachFormula x y = do
+          putStrLn $ "    formula (" ++ environment x ++ ") \"" ++ equationPreview y ++ "\""
+          mImageForFormula x y
+    return $ \fo -> withItemBody $ unsafeCompiler . convertAllFormulaeDataURIWith eachFormula fo
+  where
+    drawFormula x y = do
+      putStrLn "      drawing..."
+      imageForFormula eo x y
+
+-- | A formula compiler that does not use caching, which works in a more drop-in fashion, as in:
+--
+-- > compile $ pandocCompilerWithTransformM (compileFormulaeDataURI defaultEnv defaultPandocFormulaOptions)
+--
+compileFormulaeDataURI :: EnvironmentOptions
+                       -> PandocFormulaOptions
+                       -> Item Pandoc -> Compiler (Item Pandoc)
+compileFormulaeDataURI eo po =
+    let eachFormula x y = do
+          putStrLn $ "    formula (" ++ environment x ++ ") \"" ++ equationPreview y ++ "\""
+          putStrLn   "      drawing..."
+          imageForFormula eo x y
+    in withItemBody $ unsafeCompiler . convertAllFormulaeDataURIWith eachFormula po
+
+equationPreview :: String -> String
+equationPreview (dropWhile isSpace -> x)
+      | length x <= 16 = x
+      | otherwise      = take 16 $ filter (/= '\n') x ++ "..."
+
+memoizeLru :: Ord a => Maybe Integer -> (a -> IO b) -> IO (a -> IO b)
+memoizeLru msize action = do
+    lru <- LRU.newAtomicLRU msize
+    return $ \arg -> do
+        mret <- LRU.lookup arg lru
+        case mret of
+            Just ret -> return ret
+            Nothing -> do
+                ret <- action arg
+                LRU.insert arg ret lru
+                return ret
