diff --git a/hakyll.cabal b/hakyll.cabal
--- a/hakyll.cabal
+++ b/hakyll.cabal
@@ -1,5 +1,5 @@
 Name:               hakyll
-Version:            2.1.1
+Version:            2.2
 
 Synopsis:           A simple static site generator library.
 Description:        A simple static site generator library, mainly aimed at
@@ -28,18 +28,18 @@
   ghc-options:      -Wall
   hs-source-dirs:   src
   build-depends:    base >= 4 && < 5,
-                    filepath >= 1.1,
-                    directory >= 1,
-                    containers >= 0.1,
-                    pandoc >= 1,
-                    regex-base >= 0.83,
-                    regex-tdfa >= 0.92,
-                    network >= 2,
-                    mtl >= 1.1,
-                    old-locale >= 1,
-                    old-time >= 1,
-                    time >= 1,
-                    binary >= 0.5
+                    filepath == 1.1.*,
+                    directory == 1.0.*,
+                    containers == 0.3.*,
+                    pandoc == 1.5.*,
+                    regex-base == 0.93.*,
+                    regex-tdfa == 1.1.*,
+                    network == 2.2.*,
+                    mtl == 1.1.*,
+                    old-locale == 1.0.*,
+                    old-time == 1.0.*,
+                    time == 1.2.*,
+                    binary == 0.5.*
   exposed-modules:  Network.Hakyll.SimpleServer
                     Text.Hakyll
                     Text.Hakyll.Context
diff --git a/src/Text/Hakyll.hs b/src/Text/Hakyll.hs
--- a/src/Text/Hakyll.hs
+++ b/src/Text/Hakyll.hs
@@ -15,7 +15,7 @@
 
 import Control.Monad.Reader (runReaderT, liftIO, ask)
 import Control.Monad (when)
-import qualified Data.Map as M
+import Data.Monoid (mempty)
 import System.Environment (getArgs, getProgName)
 import System.Directory (doesDirectoryExist, removeDirectoryRecursive)
 
@@ -44,10 +44,11 @@
 
 -- | The default hakyll configuration.
 --
-defaultHakyllConfiguration :: HakyllConfiguration
-defaultHakyllConfiguration = HakyllConfiguration
-    { absoluteUrl         = ""
-    , additionalContext   = M.empty
+defaultHakyllConfiguration :: String               -- ^ Absolute site URL.
+                           -> HakyllConfiguration  -- ^ Default config.
+defaultHakyllConfiguration absoluteUrl' = HakyllConfiguration
+    { absoluteUrl         = absoluteUrl'
+    , additionalContext   = mempty
     , siteDirectory       = "_site"
     , cacheDirectory      = "_cache"
     , enableIndexUrl      = False
@@ -64,7 +65,7 @@
        -> IO ()
 hakyll absolute = hakyllWithConfiguration configuration
   where
-    configuration = defaultHakyllConfiguration { absoluteUrl = absolute }
+    configuration = defaultHakyllConfiguration absolute
 
 -- | Main function to run hakyll with a custom configuration.
 --
diff --git a/src/Text/Hakyll/Context.hs b/src/Text/Hakyll/Context.hs
--- a/src/Text/Hakyll/Context.hs
+++ b/src/Text/Hakyll/Context.hs
@@ -1,11 +1,16 @@
 -- | This (quite small) module exports the datatype used for contexts. A
 --   @Context@ is a simple key-value mapping. You can render these @Context@s
 --   with templates, and manipulate them in various ways.
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
 module Text.Hakyll.Context
-    ( Context
+    ( Context (..)
     ) where
 
+import Data.Monoid (Monoid)
 import Data.Map (Map)
+import Data.Binary (Binary)
 
 -- | Datatype used for key-value mappings.
-type Context = Map String String
+newtype Context = Context { -- | Extract the context.
+                            unContext :: Map String String
+                          } deriving (Show, Monoid, Binary)
diff --git a/src/Text/Hakyll/ContextManipulations.hs b/src/Text/Hakyll/ContextManipulations.hs
--- a/src/Text/Hakyll/ContextManipulations.hs
+++ b/src/Text/Hakyll/ContextManipulations.hs
@@ -21,7 +21,7 @@
 
 import Text.Hakyll.Regex (substituteRegex)
 import Text.Hakyll.HakyllAction (HakyllAction (..))
-import Text.Hakyll.Context (Context)
+import Text.Hakyll.Context (Context (..))
 
 -- | Do something with a value in a @Context@, but keep the old value as well.
 --   If the key given is not present in the @Context@, nothing will happen.
@@ -29,7 +29,7 @@
             -> String             -- ^ Key the value should be copied to.
             -> (String -> String) -- ^ Function to apply on the value.
             -> HakyllAction Context Context
-renderValue source destination f = arr $ \context ->
+renderValue source destination f = arr $ \(Context context) -> Context $
     case M.lookup source context of
         Nothing      -> context
         (Just value) -> M.insert destination (f value) context
diff --git a/src/Text/Hakyll/CreateContext.hs b/src/Text/Hakyll/CreateContext.hs
--- a/src/Text/Hakyll/CreateContext.hs
+++ b/src/Text/Hakyll/CreateContext.hs
@@ -42,7 +42,7 @@
 createCustomPage url association = HakyllAction
     { actionDependencies = dataDependencies
     , actionUrl          = Left $ return url
-    , actionFunction     = \_ -> M.fromList <$> assoc'
+    , actionFunction     = \_ -> Context . M.fromList <$> assoc'
     }
   where
     mtuple (a, b) = b >>= \b' -> return (a, b')
@@ -80,7 +80,8 @@
     { actionDependencies = actionDependencies x ++ actionDependencies y
     , actionUrl          = actionUrl x
     , actionFunction     = \_ ->
-        liftM2 M.union (runHakyllAction x) (runHakyllAction y)
+        Context <$> liftM2 (M.union) (unContext <$> runHakyllAction x)
+                                     (unContext <$> runHakyllAction y)
     }
 
 -- | Combine two @Context@s and set a custom URL. This behaves like @combine@,
@@ -91,7 +92,8 @@
                -> HakyllAction () Context
 combineWithUrl url x y = combine'
     { actionUrl          = Left $ return url
-    , actionFunction     = \_ -> M.insert "url" url <$> runHakyllAction combine'
+    , actionFunction     = \_ ->
+        Context . M.insert "url" url . unContext <$> runHakyllAction combine'
     }
   where
     combine' = combine x y
diff --git a/src/Text/Hakyll/Feed.hs b/src/Text/Hakyll/Feed.hs
--- a/src/Text/Hakyll/Feed.hs
+++ b/src/Text/Hakyll/Feed.hs
@@ -28,7 +28,7 @@
 import Data.Maybe (fromMaybe)
 import qualified Data.Map as M
 
-import Text.Hakyll.Context (Context)
+import Text.Hakyll.Context (Context (..))
 import Text.Hakyll.CreateContext (createListing)
 import Text.Hakyll.ContextManipulations (renderDate)
 import Text.Hakyll.HakyllMonad (Hakyll)
@@ -69,8 +69,8 @@
         ] ++ updated
 
     -- Take the first timestamp, which should be the most recent.
-    updated = let action = createHakyllAction $
-                                return . fromMaybe "foo" . M.lookup "timestamp"
+    updated = let action = createHakyllAction $ return . fromMaybe "foo" 
+                                              . M.lookup "timestamp" . unContext
                   toTuple r = ("timestamp", Right $ r >>> action)
               in map toTuple $ take 1 renderables
             
diff --git a/src/Text/Hakyll/HakyllMonad.hs b/src/Text/Hakyll/HakyllMonad.hs
--- a/src/Text/Hakyll/HakyllMonad.hs
+++ b/src/Text/Hakyll/HakyllMonad.hs
@@ -12,7 +12,7 @@
 
 import Text.Pandoc (ParserState, WriterOptions)
 
-import Text.Hakyll.Context (Context)
+import Text.Hakyll.Context (Context (..))
 
 -- | Our custom monad stack.
 type Hakyll = ReaderT HakyllConfiguration IO
@@ -50,5 +50,5 @@
 
 getAdditionalContext :: HakyllConfiguration -> Context
 getAdditionalContext configuration =
-    M.insert "absolute" (absoluteUrl configuration)
-             (additionalContext configuration)
+    let (Context c) = additionalContext configuration
+    in Context $ M.insert "absolute" (absoluteUrl configuration) c
diff --git a/src/Text/Hakyll/Internal/Page.hs b/src/Text/Hakyll/Internal/Page.hs
--- a/src/Text/Hakyll/Internal/Page.hs
+++ b/src/Text/Hakyll/Internal/Page.hs
@@ -12,7 +12,7 @@
 
 import Text.Pandoc
 
-import Text.Hakyll.Context (Context)
+import Text.Hakyll.Context (Context (..))
 import Text.Hakyll.File
 import Text.Hakyll.HakyllMonad
 import Text.Hakyll.Regex (substituteRegex, matchesRegex)
@@ -22,8 +22,9 @@
 
 -- | Get a render function for a given extension.
 getRenderFunction :: FileType -> Hakyll (String -> String)
-getRenderFunction Html     = return id
-getRenderFunction Text     = return id
+getRenderFunction Html = return id
+getRenderFunction Text = return id
+getRenderFunction UnknownFileType = return id
 getRenderFunction fileType = do
     parserState <- askHakyll pandocParserState
     writerOptions <- askHakyll pandocWriterOptions
@@ -102,7 +103,7 @@
         context = M.fromList $
             ("url", url) : ("path", path) : category ++ sectionsData
 
-    return context
+    return $ Context context
   where
     category = let dirs = splitDirectories $ takeDirectory path
                in [("category", last dirs) | not (null dirs)]
diff --git a/src/Text/Hakyll/Internal/Template.hs b/src/Text/Hakyll/Internal/Template.hs
--- a/src/Text/Hakyll/Internal/Template.hs
+++ b/src/Text/Hakyll/Internal/Template.hs
@@ -7,18 +7,19 @@
     , finalSubstitute
     ) where
 
-import qualified Data.Map as M
+import Control.Applicative ((<$>))
 import Data.List (isPrefixOf)
 import Data.Char (isAlphaNum)
 import Data.Binary
 import Control.Monad (liftM, liftM2)
 import Data.Maybe (fromMaybe)
 import System.FilePath ((</>))
-import Control.Monad.Reader (liftIO)
+import qualified Data.Map as M
 
-import Text.Hakyll.Context (Context)
+import Text.Hakyll.Context (Context (..))
 import Text.Hakyll.HakyllMonad (Hakyll)
 import Text.Hakyll.Internal.Cache
+import Text.Hakyll.Internal.Page
 
 -- | Datatype used for template substitutions.
 data Template = Chunk String Template
@@ -44,11 +45,15 @@
 readTemplate :: FilePath -> Hakyll Template
 readTemplate path = do
     isCacheMoreRecent' <- isCacheMoreRecent fileName [path]
-    if isCacheMoreRecent' then getFromCache fileName
-                          else do content <- liftIO $ readFile path
-                                  let template = fromString content
-                                  storeInCache template fileName
-                                  return template
+    if isCacheMoreRecent'
+        then getFromCache fileName
+        else do
+            page <- unContext <$> readPage path
+            let body = fromMaybe (error $ "No body in template " ++ fileName)
+                                 (M.lookup "body" page)
+                template = fromString body
+            storeInCache template fileName
+            return template
   where 
     fileName = "templates" </> path
 
@@ -61,7 +66,7 @@
 substitute escaper (Identifier key template) context =
     replacement ++ substitute escaper template context
   where
-    replacement = fromMaybe ('$' : key) $ M.lookup key context
+    replacement = fromMaybe ('$' : key) $ M.lookup key $ unContext context
 substitute escaper (EscapeCharacter template) context =
     escaper ++ substitute escaper template context
 substitute _ End _ = []
diff --git a/src/Text/Hakyll/Render.hs b/src/Text/Hakyll/Render.hs
--- a/src/Text/Hakyll/Render.hs
+++ b/src/Text/Hakyll/Render.hs
@@ -16,7 +16,7 @@
 import Data.Maybe (fromMaybe)
 import qualified Data.Map as M
 
-import Text.Hakyll.Context (Context)
+import Text.Hakyll.Context (Context (..))
 import Text.Hakyll.HakyllMonad (Hakyll, askHakyll, getAdditionalContext)
 import Text.Hakyll.File
 import Text.Hakyll.HakyllAction
@@ -27,12 +27,12 @@
 pureRender :: Template -- ^ Template to use for rendering.
            -> Context  -- ^ Renderable object to render with given template.
            -> Context  -- ^ The body of the result will contain the render.
-pureRender template context =
+pureRender template (Context c) =
     -- Ignore $root when substituting here. We will only replace that in the
     -- final render (just before writing).
-    let contextIgnoringRoot = M.insert "root" "$root" context
-        body = regularSubstitute template contextIgnoringRoot
-    in M.insert "body" body context
+    let contextIgnoringRoot = Context $ M.insert "root" "$root" c
+        body = regularSubstitute template $ contextIgnoringRoot
+    in Context $ M.insert "body" body c
 
 -- | This is the most simple render action. You render a @Context@ with a
 --   template, and get back the result.
@@ -68,7 +68,7 @@
 
     actionFunction' _ = do
         contexts <- mapM runHakyllAction renders
-        return $ concatMap (fromMaybe "" . M.lookup "body") contexts
+        return $ concatMap (fromMaybe "" . M.lookup "body" . unContext) contexts
 
 -- | Chain a render action for a page with a number of templates. This will
 --   also write the result to the site destination. This is the preferred way
@@ -112,8 +112,8 @@
 -- | Write a page to the site destination. Final action after render
 --   chains and such.
 writePage :: HakyllAction Context ()
-writePage = createHakyllAction $ \initialContext -> do
-    additionalContext' <- askHakyll getAdditionalContext
+writePage = createHakyllAction $ \(Context initialContext) -> do
+    additionalContext' <- unContext <$> askHakyll getAdditionalContext
     let url = fromMaybe (error "No url defined at write time.")
                         (M.lookup "url" initialContext)
         body = fromMaybe "" (M.lookup "body" initialContext)
@@ -121,4 +121,5 @@
     destination <- toDestination url
     makeDirectories destination
     -- Substitute $root here, just before writing.
-    liftIO $ writeFile destination $ finalSubstitute (fromString body) context
+    liftIO $ writeFile destination $ finalSubstitute (fromString body)
+                                                     (Context context)
diff --git a/src/Text/Hakyll/Tags.hs b/src/Text/Hakyll/Tags.hs
--- a/src/Text/Hakyll/Tags.hs
+++ b/src/Text/Hakyll/Tags.hs
@@ -43,7 +43,7 @@
 import Control.Applicative ((<$>))
 import System.FilePath
 
-import Text.Hakyll.Context (Context)
+import Text.Hakyll.Context (Context (..))
 import Text.Hakyll.ContextManipulations (changeValue)
 import Text.Hakyll.CreateContext (createPage)
 import Text.Hakyll.HakyllMonad (Hakyll)
@@ -105,13 +105,13 @@
 readTagMap = readMap getTagsFunction
   where
     getTagsFunction = map trim . splitRegex ","
-                    . fromMaybe [] . M.lookup "tags"
+                    . fromMaybe [] . M.lookup "tags" . unContext
 
 -- | Read a @TagMap@, using the subdirectories the pages are placed in.
 readCategoryMap :: String     -- ^ Unique identifier for the map.
                 -> [FilePath] -- ^ Paths to get tags from.
                 -> HakyllAction () TagMap
-readCategoryMap = readMap $ maybeToList . M.lookup "category"
+readCategoryMap = readMap $ maybeToList . M.lookup "category" . unContext
 
 withTagMap :: HakyllAction () TagMap
            -> (String -> [HakyllAction () Context] -> Hakyll ())
@@ -131,7 +131,7 @@
         return $ intercalate " " $ map (renderTag tagMap) (tagCount tagMap)
 
     renderTag tagMap (tag, count) = 
-        finalSubstitute linkTemplate $ M.fromList
+        finalSubstitute linkTemplate $ Context $ M.fromList
             [ ("size", sizeTag tagMap count)
             , ("url", urlFunction tag)
             , ("tag", tag)
