diff --git a/Hakyll/Contrib/Markdown/Link.hs b/Hakyll/Contrib/Markdown/Link.hs
new file mode 100644
--- /dev/null
+++ b/Hakyll/Contrib/Markdown/Link.hs
@@ -0,0 +1,203 @@
+{-|
+
+Set of Hakyll rules that facilitate including links to markdown files.
+
+-}
+
+{-# LANGUAGE DeriveDataTypeable         #-}
+{-# LANGUAGE FlexibleInstances          #-}
+{-# LANGUAGE Arrows                     #-}
+
+module Hakyll.Contrib.Markdown.Link
+       ( -- * Syntax
+         -- $syntax
+         Link(..)
+       , links
+       , toString
+       , linksCompiler
+       , pageWithLinksCompiler
+       , include
+       , includeList
+       , pageCompilerA, readStatePage
+       ) where
+
+import Control.Arrow
+import Control.Applicative hiding ((<|>))
+import Data.Binary
+import Data.Typeable
+import Data.Char           (isSpace, isAlphaNum)
+import Data.List           (groupBy, isPrefixOf)
+import Data.Map            (fromList, union)
+import Data.String
+import Hakyll.Core.Compiler(getResourceString, Compiler, requireA, cached)
+import Hakyll.Core.Identifier(Identifier)
+import Hakyll.Core.Resource(Resource)
+import Hakyll.Core.Writable(Writable(..))
+import Hakyll.Web.Pandoc ( defaultHakyllParserState
+                         , pageReadPandocWithA
+                         , writePandoc
+                         )
+import Hakyll.Web.Template(applySelf)
+import Hakyll.Web.Page(addDefaultFields, readPageCompiler, Page)
+import Text.Pandoc.Parsing(toKey, ParserState(..))
+import Text.Pandoc.Definition hiding (Link)
+import Text.Parsec.String  (Parser)
+import Text.Parsec
+
+
+
+-- | The link data type.
+data Link = Link { linkRef     :: [String] -- ^ reference to this link
+                 , linkUrl     ::  String  -- ^ destination url
+                 , linkTitle   :: [String] -- ^ link title string.
+                 } deriving (Show, Eq, Typeable)
+
+instance IsString Link where
+  fromString s = either err id $ parse linkP "<>" s
+        where err e = error $ "bad link:" ++ show e
+
+
+instance Binary Link where
+  put lnk = do put $ linkRef lnk
+               put $ linkUrl lnk
+               put $ linkTitle lnk
+  get     = Link <$> get <*> get <*> get
+
+instance Writable [Link] where
+  write fp = write fp . unlines . map toString
+
+-- | Cache name used by this module.
+cacheName :: String
+cacheName = "Hakyll.Contrib.Markdown.Link"
+
+-- | The Hakyll compiler that reads a list of links.
+linksCompiler :: Compiler Resource [Link]
+linksCompiler = cached cacheName $ getResourceString >>> arr links
+
+-- | Compiles a pandoc page with a give list of links database.
+pageWithLinksCompiler :: [Identifier [Link]] -- ^ The links db's
+                      -> Compiler Resource (Page String)
+pageWithLinksCompiler ids = cached cacheName $
+      readStatePage >>> includeList ids >>> pageCompilerA
+
+-- | A compiler that modified the Pandoc parser state to accomodate a
+-- set of link definitions.
+include :: Identifier [Link]  -- ^ The link database identifier
+        -> Compiler (ParserState,a) (ParserState,a)
+include ident = first $ requireA ident $ arr combine
+   where combine (ps,lns)= ps { stateKeys = stateKeys ps `union`
+                                            toKeyTable lns
+                              }
+         toKeyTable = fromList . map kvPair
+         kvPair (Link r u t) = (toKey $ map Str r, (u, unwords t))
+
+
+-- | Similar to include but includes a list of link definitions.
+includeList :: [Identifier [Link]] -- ^ The list of link database
+                                   -- identifiers.
+            -> Compiler (ParserState,a) (ParserState, a)
+
+includeList =  foldl1 (>>>) . map include
+
+-- | A version of page compiler useful for including
+readStatePage :: Compiler Resource (ParserState, Page String)
+readStatePage = proc res -> do page    <- readPageCompiler -< res
+                               returnA -< (defaultHakyllParserState, page)
+
+
+-- | Compilers with a given parser state.
+pageCompilerA :: Compiler (ParserState, Page String) (Page String)
+pageCompilerA = second fieldsAndTemplate >>> pageReadPandocWithA >>> writer
+   where fieldsAndTemplate = addDefaultFields >>> arr applySelf
+         writer    = arr $ fmap writePandoc
+
+-- | Convert the link to string.
+toString :: Link -> String
+toString lnk = concat [ "[", r, "]"
+                      , ": "
+                      , "<", linkUrl lnk, ">"
+                      , t
+                      ]
+   where r = unwords $ map escapeRef   $ linkRef   lnk
+         t = unwords $ map escapeTitle $ linkTitle lnk
+
+
+escapeRef :: String -> String
+escapeRef = concatMap esc
+  where esc c | isAlphaNum c || c `elem` refSpChars = [c]
+              | otherwise                           = escapeChar : [c]
+
+escapeTitle :: String -> String
+escapeTitle = concatMap esc
+  where esc c | isSpace c = escapeChar : [c]
+              | otherwise = [c]
+
+-- | Link parser
+linkP  :: Parser Link
+
+
+-- | Convert a parser to a lexeme parser.
+lexeme :: Parser a -> Parser a
+lexeme p = p <* spaces
+
+-- | An escape char
+escape :: Parser Char
+escape = char escapeChar >> anyChar
+
+-- | The special characters in references.
+refSpChars :: [Char]
+refSpChars = "#_-:"
+
+-- | A link reference
+ref :: Parser [String]
+ref     = many1 refWord <?> "link-reference"
+   where refChar = escape <|> alphaNum <|> oneOf refSpChars
+         refWord = lexeme $ many1 refChar
+
+-- | A url
+url  :: Parser String
+url  = lexeme (between langle rangle $ many1 $ noneOf ">")
+       <?> "URL"
+  where langle  = lexeme $ char '<'
+        rangle  = lexeme $ char '>'
+
+-- | A link title
+title :: Parser [String]
+title = many1 titleWord <?> "link-title"
+  where titleChar = escape <|> satisfy (not . isSpace)
+        titleWord = lexeme $ many1 titleChar
+
+linkP = Link <$> lref <* colon <*> url <*> option [] title
+  where lref    = between lbrack rbrack ref <?> "[link-reference]"
+        colon    = lexeme $ char ':'
+        lbrack   = lexeme $ char '['
+        rbrack   = lexeme $ char ']'
+
+
+-- $syntax
+--
+-- We use the markdown syntax to provide links namely
+--
+-- > [linkname]: <url> Comment
+--
+-- Multiple lines are folded if the are intended atleast by a space.
+-- All lines that start with a @'--'@ (two hyphens) are treated as
+-- comments and skipped.
+
+-- | Convert a set of lines to links.
+links :: String -> [Link]
+links = map fromString
+      . map combine
+      . indent
+      . filter (not . commentLine)
+      . filter (not . null)
+      . lines
+  where indent = groupBy (\ _ -> isSpace . head)
+        combine []     = []
+        combine (x:xs) = concat (x: map tail xs)
+        commentLine    = isPrefixOf commentStart
+
+escapeChar   :: Char
+commentStart :: String
+escapeChar   = '\\'
+commentStart = "--"
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2012, Piyush P Kurur
+
+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 Piyush P Kurur 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.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,4 @@
+#!/usr/bin/env runhaskell
+
+> import Distribution.Simple
+> main = defaultMain
diff --git a/hakyll-contrib-links.cabal b/hakyll-contrib-links.cabal
new file mode 100644
--- /dev/null
+++ b/hakyll-contrib-links.cabal
@@ -0,0 +1,43 @@
+name: hakyll-contrib-links
+version: 0.1.0.0
+synopsis: A hakyll library that helps maintain a separate links database.
+
+description: Often when building packages we would like to collect all
+  commonly occuring urls in a separate file and include it in all
+  pages. This module facilitates maintaining such links database and
+  including it with different pages. The syntax of the links database
+  is that of markdown.
+
+license: BSD3
+license-file: LICENSE
+author: Piyush P Kurur
+maintainer: ppk@cse.iitk.ac.in
+category: Web, Hakyll
+build-type: Simple
+cabal-version: >=1.9.2
+
+library
+  build-depends: base ==4.5.*
+               , containers ==0.4.*
+               , binary ==0.5.*
+               , parsec ==3.*
+               , hakyll ==3.*
+               , pandoc ==1.9.*
+               , pandoc-types ==1.9.*
+  exposed-modules: Hakyll.Contrib.Markdown.Link
+  ghc-Options: -Wall
+test-Suite tests
+  type: exitcode-stdio-1.0
+  hs-source-dirs: tests
+  main-is: Main.hs
+  build-depends: base==4.5.*
+               , binary ==0.5.*
+               , test-framework==0.6.*
+               , test-framework-quickcheck2==0.2.*
+               , QuickCheck==2.4.*
+               , hakyll-contrib-links
+
+Source-repository this
+  type: darcs
+  location: http://patch-tag.com/r/ppk/hakyll-contrib-links
+  tag: 0.1.0.0-RELEASE
diff --git a/tests/Main.hs b/tests/Main.hs
new file mode 100644
--- /dev/null
+++ b/tests/Main.hs
@@ -0,0 +1,8 @@
+module Main where
+
+import Test.Framework (defaultMain, testGroup)
+import qualified Modules.Markdown.Link as L
+main = defaultMain tests
+
+tests = [testGroup "Hakyll.Markdown.Link" L.tests]
+
