diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2015 Matthew Pickering
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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/servant-pandoc.cabal b/servant-pandoc.cabal
new file mode 100644
--- /dev/null
+++ b/servant-pandoc.cabal
@@ -0,0 +1,68 @@
+-- Initial servant-pandoc.cabal generated by cabal init.  For further
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+-- The name of the package.
+name:                servant-pandoc
+
+-- The package version.  See the Haskell package versioning policy (PVP)
+-- for standards guiding when and how versions should be incremented.
+-- http://www.haskell.org/haskellwiki/Package_versioning_policy
+-- PVP summary:      +-+------- breaking API changes
+--                   | | +----- non-breaking API additions
+--                   | | | +--- code changes with no API change
+version:             0.1
+
+-- A short (one-line) description of the package.
+synopsis:            Use Pandoc to render servant API documentation
+
+-- A longer description of the package.
+-- description:
+
+-- The license under which the package is released.
+license:             MIT
+
+-- The file containing the license text.
+license-file:        LICENSE
+
+-- The package author(s).
+author:              Matthew Pickering
+
+-- An email address to which users can send suggestions, bug reports, and
+-- patches.
+maintainer:          matthewtpickering@gmail.com
+
+-- A copyright notice.
+-- copyright:
+
+category:            Web
+
+build-type:          Simple
+
+-- Extra files to be distributed with the package, such as examples or a
+-- README.
+-- extra-source-files:
+
+-- Constraint on the version of Cabal needed to build this package.
+cabal-version:       >=1.10
+
+
+library
+  -- Modules exported by the library.
+  exposed-modules:     Servant.Docs.Pandoc
+
+  -- Modules included in this library but not exported.
+  -- other-modules:
+
+  -- LANGUAGE extensions used by modules in this package.
+  other-extensions:    OverloadedStrings
+
+  -- Other library packages from which modules are imported.
+  build-depends:       base >=4.7 && <4.8, pandoc-types >=1.12 && <1.13, servant-docs >=0.3 && <0.4, unordered-containers >=0.2 && <0.3, text >=1.2 && <1.3, bytestring >=0.10 && <0.11
+
+  -- Directories containing source files.
+  hs-source-dirs:      src
+
+  -- Base language which the package is written in.
+  default-language:    Haskell2010
+  ghc-options: -Wall
+
diff --git a/src/Servant/Docs/Pandoc.hs b/src/Servant/Docs/Pandoc.hs
new file mode 100644
--- /dev/null
+++ b/src/Servant/Docs/Pandoc.hs
@@ -0,0 +1,148 @@
+{-# LANGUAGE OverloadedStrings #-}
+----------------------------------
+-- | There are two ways in which to use this module.
+--
+-- The first is to use the renderer directly with the pandoc API.
+-- A very simple
+-- program to render the API documentation as a mediawiki document might look as
+-- follows.
+--
+-- > import Text.Pandoc
+-- > import Sevant.Docs.Pandoc
+-- > import Data.Default (def)
+-- >
+-- > myApi :: Proxy MyAPI
+-- > myApi = Proxy
+-- >
+-- > writeDocs :: API -> IO ()
+-- > writeDocs api = writeMediaWiki def (pandoc api) >>= writeFile "api.mw"
+--
+-- The second approach is to use `makeFilter` to make a filter which can be
+-- used directly with pandoc from the command line. This filter will just
+-- append the API documentation to the end of the document.
+-- Example usage
+--
+-- > -- api.hs
+-- > main :: IO ()
+-- > main = makeFilter (docs myApi)
+--
+-- >> pandoc -o api.pdf --filter=api.hs manual.md
+module Servant.Docs.Pandoc (pandoc, makeFilter) where
+
+import qualified Text.Pandoc.Builder as B
+import Text.Pandoc.Builder (Blocks, Inlines)
+import Text.Pandoc.Definition (Pandoc)
+import Text.Pandoc.JSON (toJSONFilter)
+import Servant.Docs
+import qualified Data.HashMap.Strict as HM
+import Data.Text (Text, unpack)
+import Data.List (intercalate)
+import Data.ByteString.Lazy (ByteString)
+import qualified Data.ByteString.Lazy.Char8 as B (unpack)
+
+
+-- | Helper function which can be used to make a pandoc filter which
+-- appends the generate docs to the end of the document.
+--
+-- This function is exposed for convenience. More experienced authors can
+-- of course define a more complicated filter to inject the API
+-- documentation.
+makeFilter :: API -> IO ()
+makeFilter api = toJSONFilter inject
+  where
+    inject :: Pandoc -> Pandoc
+    inject p = p <> pandoc api
+
+
+-- | Generate a `Pandoc` representation of a given
+-- `API`.
+pandoc :: API -> Pandoc
+pandoc = B.doc . mconcat . map (uncurry printEndpoint) . HM.toList
+
+  where printEndpoint :: Endpoint -> Action -> Blocks
+        printEndpoint endpoint action =
+          B.header 1 str <>
+          capturesStr (action ^. captures) <>
+          headersStr (action ^. headers) <>
+          paramsStr (action ^. params) <>
+          rqbodyStr (action ^. rqbody) <>
+          responseStr (action ^. response)
+
+          where str :: Inlines
+                str = B.str (show (endpoint^.method)) <> B.space <> B.code (intercalate "/" (endpoint ^. path))
+
+        capturesStr :: [DocCapture] -> Blocks
+        capturesStr [] = mempty
+        capturesStr l =
+          B.header 2 "Captures" <>
+          B.bulletList (map captureStr l)
+        captureStr cap =
+          B.plain $ B.emph (B.doubleQuoted . B.str$ (cap ^. capSymbol)) <>  ":" <> B.space <>  B.str (cap ^. capDesc)
+
+        headersStr :: [Text] -> Blocks
+        headersStr [] = mempty
+        headersStr l =  B.bulletList (map (B.para . headerStr) l)
+
+          where headerStr hname = "This endpoint is sensitive to the value of the" <> B.space <>
+                                    (B.strong . B.str  $ unpack hname) <> B.space <> "HTTP header."
+
+        paramsStr :: [DocQueryParam] -> Blocks
+        paramsStr [] = mempty
+        paramsStr l =
+          B.header 2 "GET Parameters" <>
+          B.bulletList (map paramStr l)
+
+        paramStr param =
+            B.plain (B.str (param ^. paramName)) <>
+              B.definitionList (
+                [(B.strong "Values",
+                    [B.plain (B.emph
+                      (foldr (\a b -> B.str a <> B.str "," <> B.space <> b) mempty values))])
+                | not (null values) || param ^. paramKind /= Flag]
+                ++
+              [(B.strong "Description",
+                  [B.plain $ B.str (param ^. paramDesc)])])
+              <>
+              B.bulletList (
+                [B.plain $ "This parameter is a" <>
+                         B.space <>
+                         B.strong "list" <>
+                         ". All GET parameters with the name" <>
+                         B.space <>
+                         B.str (param ^. paramName) <>
+                         B.space <>
+                         B.code "[]" <> B.space <>
+                         "will forward their values in a list to the handler."
+                         | param ^. paramKind == List]
+                ++
+              [B.plain $ "This parameter is a" <>
+                          B.space <>
+                          B.strong "flag." <>
+                          B.space <>
+                          "This means no value is expected to be associated to this parameter."
+              | param ^. paramKind == Flag]
+          )
+
+
+          where values = param ^. paramValues
+
+        rqbodyStr :: Maybe ByteString -> Blocks
+        rqbodyStr Nothing = mempty
+        rqbodyStr (Just b) =
+          B.header 2 "Request Body" <>
+          jsonStr b
+
+        jsonStr :: ByteString -> Blocks
+        jsonStr b =
+          B.codeBlockWith ("",["javascript"],[]) (B.unpack b)
+
+        responseStr :: Response -> Blocks
+        responseStr resp =
+          B.header 2 "Response"  <>
+          B.bulletList (
+            [B.plain $ "Status code" <> B.space <> (B.str . show) (resp ^. respStatus)]
+              ++
+            (resp ^. respBody &
+              maybe [B.plain "No response body"]
+                    (\b -> [B.plain "Response body as below." <> jsonStr b])))
+
