diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2014, Zalora South East Asia Pte Ltd
+
+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 Zalora South East Asia Pte Ltd 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/example/greet.hs b/example/greet.hs
new file mode 100644
--- /dev/null
+++ b/example/greet.hs
@@ -0,0 +1,62 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE OverloadedStrings #-}
+import Data.Aeson
+import Data.Text
+import GHC.Generics
+import Servant
+import Servant.Docs
+
+-- * Example
+
+-- | A greet message data type
+newtype Greet = Greet { msg :: Text }
+  deriving (Generic, Show)
+
+instance FromJSON Greet
+instance ToJSON Greet
+
+-- We add some useful annotations to our captures,
+-- query parameters and request body to make the docs
+-- really helpful.
+instance ToCapture (Capture "name" Text) where
+  toCapture _ = DocCapture "name" "name of the person to greet"
+
+instance ToCapture (Capture "greetid" Text) where
+  toCapture _ = DocCapture "greetid" "identifier of the greet msg to remove"
+
+instance ToParam (QueryParam "capital" Bool) where
+  toParam _ =
+    DocQueryParam "capital"
+                  ["true", "false"]
+                  "Get the greeting message in uppercase (true) or not (false). Default is false."
+                  Normal
+
+instance ToSample Greet where
+  toSample = Just $ Greet "Hello, haskeller!"
+
+-- API specification
+type TestApi =
+       -- GET /hello/:name?capital={true, false}  returns a Greet as JSON
+       "hello" :> Capture "name" Text :> QueryParam "capital" Bool :> Get Greet
+
+       -- POST /greet with a Greet as JSON in the request body,
+       --             returns a Greet as JSON
+  :<|> "greet" :> ReqBody Greet :> Post Greet
+
+       -- DELETE /greet/:greetid
+  :<|> "greet" :> Capture "greetid" Text :> Delete
+
+testApi :: Proxy TestApi
+testApi = Proxy
+
+-- Generate the data that lets us have API docs. This
+-- is derived from the type as well as from
+-- the 'ToCapture', 'ToParam' and 'ToSample' instances from above.
+docsGreet :: API
+docsGreet = docs testApi
+
+main :: IO ()
+main = putStrLn $ markdown docsGreet
diff --git a/servant-docs.cabal b/servant-docs.cabal
new file mode 100644
--- /dev/null
+++ b/servant-docs.cabal
@@ -0,0 +1,100 @@
+name:                servant-docs
+version:             0.2
+synopsis:            generate API docs for your servant webservice
+description:
+  Library for generating API docs from a servant API definition.
+  .
+  Runnable example below that prints API docs in markdown.
+  .
+  > {-# LANGUAGE DataKinds #-}
+  > {-# LANGUAGE PolyKinds #-}
+  > {-# LANGUAGE TypeFamilies #-}
+  > {-# LANGUAGE DeriveGeneric #-}
+  > {-# LANGUAGE TypeOperators #-}
+  > {-# LANGUAGE FlexibleInstances #-}
+  > {-# LANGUAGE OverloadedStrings #-}
+  >
+  > import Data.Proxy
+  > import Data.Text
+  > import Servant
+  >
+  > -- our type for a Greeting message
+  > data Greet = Greet { _msg :: Text }
+  >   deriving (Generic, Show)
+  >
+  > -- we get our JSON serialization for free
+  > instance FromJSON Greet
+  > instance ToJSON Greet
+  >
+  > -- we provide a sample value for the 'Greet' type
+  > instance ToSample Greet where
+  >   toSample = Just g
+  >
+  >     where g = Greet "Hello, haskeller!"
+  >
+  > instance ToParam (QueryParam "capital" Bool) where
+  >   toParam _ =
+  >     DocQueryParam "capital"
+  >                   ["true", "false"]
+  >                   "Get the greeting message in uppercase (true) or not (false). Default is false."
+  >
+  > instance ToCapture (Capture "name" Text) where
+  >   toCapture _ = DocCapture "name" "name of the person to greet"
+  >
+  > instance ToCapture (Capture "greetid" Text) where
+  >   toCapture _ = DocCapture "greetid" "identifier of the greet msg to remove"
+  >
+  > -- API specification
+  > type TestApi =
+  >        "hello" :> Capture "name" Text :> QueryParam "capital" Bool :> Get Greet
+  >   :<|> "greet" :> RQBody Greet :> Post Greet
+  >   :<|> "delete" :> Capture "greetid" Text :> Delete
+  >
+  > testApi :: Proxy TestApi
+  > testApi = Proxy
+  >
+  > -- Generate the Documentation's ADT
+  > greetDocs :: API
+  > greetDocs = docs testApi
+  >
+  > main :: IO ()
+  > main = putStrLn $ markdown greetDocs
+license:             BSD3
+license-file:        LICENSE
+author:              Alp Mestanogullari, Sönke Hahn, Julian K. Arni
+maintainer:          alpmestan@gmail.com
+copyright:           2014 Zalora South East Asia Pte Ltd
+category:            Web
+build-type:          Simple
+cabal-version:       >=1.10
+tested-with:         GHC >= 7.8
+homepage:            http://haskell-servant.github.io/
+Bug-reports:         http://github.com/haskell-servant/servant-docs/issues
+source-repository head
+  type: git
+  location: http://github.com/haskell-servant/servant-docs.git
+
+library
+  exposed-modules:
+    Servant.Docs
+  build-depends:
+      base >=4.7 && <5
+    , aeson
+    , bytestring
+    , hashable
+    , lens
+    , servant >= 0.2
+    , string-conversions
+    , system-filepath
+    , text
+    , unordered-containers
+  hs-source-dirs: src
+  default-language: Haskell2010
+  ghc-options: -Wall
+
+executable greet-docs
+  main-is: greet.hs
+  hs-source-dirs: example
+  ghc-options: -Wall
+  build-depends: base, aeson, servant, servant-docs, text
+  default-language: Haskell2010
diff --git a/src/Servant/Docs.hs b/src/Servant/Docs.hs
new file mode 100644
--- /dev/null
+++ b/src/Servant/Docs.hs
@@ -0,0 +1,608 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell #-}
+
+-------------------------------------------------------------------------------
+-- | This module lets you get API docs for free. It lets generate
+-- an 'API' from the type that represents your API using 'docs':
+--
+-- @docs :: 'HasDocs' api => 'Proxy' api -> 'API'@
+--
+-- You can then call 'markdown' on it:
+--
+-- @markdown :: 'API' -> String@
+--
+-- or define a custom pretty printer:
+--
+-- @yourPrettyDocs :: 'API' -> String -- or blaze-html's HTML, or ...@
+--
+-- The only thing you'll need to do will be to implement some classes
+-- for your captures, get parameters and request or response bodies.
+--
+-- Here's a little (but complete) example that you can run to see the
+-- markdown pretty printer in action:
+--
+-- > {-# LANGUAGE DataKinds #-}
+-- > {-# LANGUAGE PolyKinds #-}
+-- > {-# LANGUAGE TypeFamilies #-}
+-- > {-# LANGUAGE DeriveGeneric #-}
+-- > {-# LANGUAGE TypeOperators #-}
+-- > {-# LANGUAGE FlexibleInstances #-}
+-- > {-# LANGUAGE OverloadedStrings #-}
+-- >
+-- > import Data.Proxy
+-- > import Data.Text
+-- > import Servant
+-- >
+-- > -- our type for a Greeting message
+-- > data Greet = Greet { _msg :: Text }
+-- >   deriving (Generic, Show)
+-- >
+-- > -- we get our JSON serialization for free
+-- > instance FromJSON Greet
+-- > instance ToJSON Greet
+-- >
+-- > -- we provide a sample value for the 'Greet' type
+-- > instance ToSample Greet where
+-- >   toSample = Just g
+-- >
+-- >     where g = Greet "Hello, haskeller!"
+-- >
+-- > instance ToParam (QueryParam "capital" Bool) where
+-- >   toParam _ =
+-- >     DocQueryParam "capital"
+-- >                   ["true", "false"]
+-- >                   "Get the greeting message in uppercase (true) or not (false). Default is false."
+-- >
+-- > instance ToCapture (Capture "name" Text) where
+-- >   toCapture _ = DocCapture "name" "name of the person to greet"
+-- >
+-- > instance ToCapture (Capture "greetid" Text) where
+-- >   toCapture _ = DocCapture "greetid" "identifier of the greet msg to remove"
+-- >
+-- > -- API specification
+-- > type TestApi =
+-- >        "hello" :> Capture "name" Text :> QueryParam "capital" Bool :> Get Greet
+-- >   :<|> "greet" :> RQBody Greet :> Post Greet
+-- >   :<|> "delete" :> Capture "greetid" Text :> Delete
+-- >
+-- > testApi :: Proxy TestApi
+-- > testApi = Proxy
+-- >
+-- > -- Generate the Documentation's ADT
+-- > greetDocs :: API
+-- > greetDocs = docs testApi
+-- >
+-- > main :: IO ()
+-- > main = putStrLn $ markdown greetDocs
+module Servant.Docs
+  ( -- * 'HasDocs' class and key functions
+    HasDocs(..), docs, markdown
+
+  {- , -- * Serving the documentation
+    serveDocumentation -}
+
+  , -- * Classes you need to implement for your types
+    ToSample(..)
+  , sampleByteString
+  , ToParam(..)
+  , ToCapture(..)
+
+  , -- * ADTs to represent an 'API'
+    Method(..)
+  , Endpoint, path, method, defEndpoint
+  , API, emptyAPI
+  , DocCapture(..), capSymbol, capDesc
+  , DocQueryParam(..), ParamKind(..), paramName, paramValues, paramDesc, paramKind
+  , Response, respStatus, respBody, defResponse
+  , Action, captures, params, rqbody, response, defAction
+  , single
+
+  , -- * Useful modules when defining your doc printers
+    module Control.Lens
+  , module Data.Monoid
+  ) where
+
+import Control.Lens hiding (Action)
+import Data.Aeson
+import Data.ByteString.Lazy.Char8 (ByteString)
+import Data.Hashable
+import Data.HashMap.Strict (HashMap)
+import Data.List
+import Data.Monoid
+import Data.Proxy
+import Data.Text (Text, pack, unpack)
+import Data.String.Conversions
+import GHC.Generics
+import GHC.TypeLits
+import Servant
+
+import qualified Data.HashMap.Strict as HM
+
+-- | Supported HTTP request methods
+data Method = DocDELETE -- ^ the DELETE method
+            | DocGET    -- ^ the GET method
+            | DocPOST   -- ^ the POST method
+            | DocPUT    -- ^ the PUT method
+  deriving (Eq, Generic)
+
+instance Show Method where
+  show DocGET = "GET"
+  show DocPOST = "POST"
+  show DocDELETE = "DELETE"
+  show DocPUT = "PUT"
+
+instance Hashable Method
+
+-- | An 'Endpoint' type that holds the 'path' and the 'method'.
+--
+-- Gets used as the key in the 'API' hashmap. Modify 'defEndpoint'
+-- or any 'Endpoint' value you want using the 'path' and 'method'
+-- lenses to tweak.
+--
+-- @
+-- λ> 'defEndpoint'
+-- GET /
+-- λ> 'defEndpoint' & 'path' '<>~' "foo"
+-- GET /foo
+-- λ> 'defEndpoint' & 'path' '<>~' "foo" & 'method' '.~' 'DocPOST'
+-- POST /foo
+-- @
+data Endpoint = Endpoint
+  { _path   :: String -- type collected
+  , _method :: Method -- type collected
+  } deriving (Eq, Generic)
+
+instance Show Endpoint where
+  show (Endpoint p m) =
+    show m ++ " " ++ p
+
+-- | An 'Endpoint' whose path is `"/"` and whose method is 'DocGET'
+--
+-- Here's how you can modify it:
+--
+-- @
+-- λ> 'defEndpoint'
+-- GET /
+-- λ> 'defEndpoint' & 'path' '<>~' "foo"
+-- GET /foo
+-- λ> 'defEndpoint' & 'path' '<>~' "foo" & 'method' '.~' 'DocPOST'
+-- POST /foo
+-- @
+defEndpoint :: Endpoint
+defEndpoint = Endpoint "/" DocGET
+
+instance Hashable Endpoint
+
+-- | Our API type, a good old hashmap from 'Endpoint' to 'Action'
+type API = HashMap Endpoint Action
+
+-- | An empty 'API'
+emptyAPI :: API
+emptyAPI = HM.empty
+
+-- | A type to represent captures. Holds the name of the capture
+--   and a description.
+--
+-- Write a 'ToCapture' instance for your captured types.
+data DocCapture = DocCapture
+  { _capSymbol :: String -- type supplied
+  , _capDesc   :: String -- user supplied
+  } deriving (Eq, Show)
+
+-- | A type to represent a /GET/ parameter from the Query String. Holds its name,
+--   the possible values (leave empty if there isn't a finite number of them),
+--   and a description of how it influences the output or behavior.
+--
+-- Write a 'ToParam' instance for your GET parameter types
+data DocQueryParam = DocQueryParam
+  { _paramName   :: String   -- type supplied
+  , _paramValues :: [String] -- user supplied
+  , _paramDesc   :: String   -- user supplied
+  , _paramKind   :: ParamKind
+  } deriving (Eq, Show)
+
+-- | Type of GET parameter:
+--
+-- - Normal corresponds to @QueryParam@, i.e your usual GET parameter
+-- - List corresponds to @QueryParams@, i.e GET parameters with multiple values
+-- - Flag corresponds to @QueryFlag@, i.e a value-less GET parameter
+data ParamKind = Normal | List | Flag
+  deriving (Eq, Show)
+
+-- | A type to represent an HTTP response. Has an 'Int' status and
+-- a 'Maybe ByteString' response body. Tweak 'defResponse' using
+-- the 'respStatus' and 'respBody' lenses if you want.
+--
+-- If you want to respond with a non-empty response body, you'll most likely
+-- want to write a 'ToSample' instance for the type that'll be represented
+-- as some JSON in the response.
+--
+-- Can be tweaked with two lenses.
+--
+-- > λ> defResponse
+-- > Response {_respStatus = 200, _respBody = Nothing}
+-- > λ> defResponse & respStatus .~ 204 & respBody .~ Just "[]"
+-- > Response {_respStatus = 204, _respBody = Just "[]"}
+data Response = Response
+  { _respStatus :: Int
+  , _respBody   :: Maybe ByteString
+  } deriving (Eq, Show)
+
+-- | Default response: status code 200, no response body.
+--
+-- Can be tweaked with two lenses.
+--
+-- > λ> defResponse
+-- > Response {_respStatus = 200, _respBody = Nothing}
+-- > λ> defResponse & respStatus .~ 204 & respBody .~ Just "[]"
+-- > Response {_respStatus = 204, _respBody = Just "[]"}
+defResponse :: Response
+defResponse = Response 200 Nothing
+
+-- | A datatype that represents everything that can happen
+-- at an endpoint, with its lenses:
+--
+-- - List of captures ('captures')
+-- - List of GET parameters ('params')
+-- - What the request body should look like, if any is requested ('rqbody')
+-- - What the response should be if everything goes well ('response')
+--
+-- You can tweak an 'Action' (like the default 'defAction') with these lenses
+-- to transform an action and add some information to it.
+data Action = Action
+  { _captures :: [DocCapture]        -- type collected + user supplied info
+  , _headers  :: [Text]              -- type collected
+  , _params   :: [DocQueryParam]     -- type collected + user supplied info
+  , _rqbody   :: Maybe ByteString    -- user supplied
+  , _response :: Response            -- user supplied
+  } deriving (Eq, Show)
+
+-- Default 'Action'. Has no 'captures', no GET 'params', expects
+-- no request body ('rqbody') and the typical response is 'defResponse'.
+--
+-- Tweakable with lenses.
+--
+-- > λ> defAction
+-- > Action {_captures = [], _params = [], _rqbody = Nothing, _response = Response {_respStatus = 200, _respBody = Nothing}}
+-- > λ> defAction & response.respStatus .~ 201
+-- > Action {_captures = [], _params = [], _rqbody = Nothing, _response = Response {_respStatus = 201, _respBody = Nothing}}
+defAction :: Action
+defAction =
+  Action []
+         []
+         []
+         Nothing
+         defResponse
+
+-- | Create an API that's comprised of a single endpoint.
+--   'API' is a 'Monoid', so combine multiple endpoints with
+--   'mappend' or '<>'.
+single :: Endpoint -> Action -> API
+single = HM.singleton
+
+-- gimme some lenses
+makeLenses ''Endpoint
+makeLenses ''DocCapture
+makeLenses ''DocQueryParam
+makeLenses ''Response
+makeLenses ''Action
+
+-- | Generate the docs for a given API that implements 'HasDocs'.
+docs :: HasDocs layout => Proxy layout -> API
+docs p = docsFor p (defEndpoint, defAction)
+
+-- | The class that abstracts away the impact of API combinators
+--   on documentation generation.
+class HasDocs layout where
+  docsFor :: Proxy layout -> (Endpoint, Action) -> API
+
+-- | The class that lets us display a sample JSON input or output
+--   when generating documentation for endpoints that either:
+--
+-- - expect a request body, or
+-- - return a non empty response body
+--
+-- Example of an instance:
+--
+-- > {-# LANGUAGE DeriveGeneric #-}
+-- > {-# LANGUAGE OverloadedStrings #-}
+-- >
+-- > import Data.Aeson
+-- > import Data.Text
+-- > import GHC.Generics
+-- >
+-- > data Greet = Greet { _msg :: Text }
+-- >   deriving (Generic, Show)
+-- >
+-- > instance FromJSON Greet
+-- > instance ToJSON Greet
+-- >
+-- > instance ToSample Greet where
+-- >   toSample = Just g
+-- >
+-- >     where g = Greet "Hello, haskeller!"
+class ToJSON a => ToSample a where
+  toSample :: Maybe a
+
+instance ToSample () where
+  toSample = Just ()
+
+sampleByteString :: forall a . ToSample a => Proxy a -> Maybe ByteString
+sampleByteString Proxy = fmap encode (toSample :: Maybe a)
+
+-- | The class that helps us automatically get documentation
+--   for GET parameters.
+--
+-- Example of an instance:
+--
+-- > instance ToParam (QueryParam "capital" Bool) where
+-- >   toParam _ =
+-- >     DocQueryParam "capital"
+-- >                   ["true", "false"]
+-- >                   "Get the greeting message in uppercase (true) or not (false). Default is false."
+class ToParam t where
+  toParam :: Proxy t -> DocQueryParam
+
+-- | The class that helps us automatically get documentation
+--   for URL captures.
+--
+-- Example of an instance:
+--
+-- > instance ToCapture (Capture "name" Text) where
+-- >   toCapture _ = DocCapture "name" "name of the person to greet"
+class ToCapture c where
+  toCapture :: Proxy c -> DocCapture
+
+-- | Generate documentation in Markdown format for
+--   the given 'API'.
+markdown :: API -> String
+markdown = unlines . concat . map (uncurry printEndpoint) . HM.toList
+
+  where printEndpoint :: Endpoint -> Action -> [String]
+        printEndpoint endpoint action =
+          str :
+          replicate len '-' :
+          "" :
+          capturesStr (action ^. captures) ++
+          headersStr (action ^. headers) ++
+          paramsStr (action ^. params) ++
+          rqbodyStr (action ^. rqbody) ++
+          responseStr (action ^. response) ++
+          []
+
+          where str = show (endpoint^.method) ++ " " ++ endpoint^.path
+                len = length str
+
+        capturesStr :: [DocCapture] -> [String]
+        capturesStr [] = []
+        capturesStr l =
+          "**Captures**: " :
+          "" :
+          map captureStr l ++
+          "" :
+          []
+        captureStr cap =
+          "- *" ++ (cap ^. capSymbol) ++ "*: " ++ (cap ^. capDesc)
+
+        headersStr :: [Text] -> [String]
+        headersStr [] = []
+        headersStr l = [""] ++ map headerStr l ++ [""]
+
+          where headerStr hname = "- This endpoint is sensitive to the value of the **"
+                               ++ unpack hname ++ "** HTTP header."
+
+        paramsStr :: [DocQueryParam] -> [String]
+        paramsStr [] = []
+        paramsStr l =
+          "**GET Parameters**: " :
+          "" :
+          map paramStr l ++
+          "" :
+          []
+        paramStr param = unlines $
+          (" - " ++ param ^. paramName) :
+          (if (not (null values) || param ^. paramKind /= Flag)
+            then ["     - **Values**: *" ++ intercalate ", " values ++ "*"]
+            else []) ++
+          ("     - **Description**: " ++ param ^. paramDesc) :
+          (if (param ^. paramKind == List)
+            then ["     - This parameter is a **list**. All GET parameters with the name "
+                  ++ param ^. paramName ++ "[] will forward their values in a list to the handler."]
+            else []) ++
+          (if (param ^. paramKind == Flag)
+            then ["     - This parameter is a **flag**. This means no value is expected to be associated to this parameter."]
+            else []) ++
+          []
+
+          where values = param ^. paramValues
+
+        rqbodyStr :: Maybe ByteString -> [String]
+        rqbodyStr Nothing = []
+        rqbodyStr (Just b) =
+          "**Request Body**: " :
+          jsonStr b
+
+        jsonStr b =
+          "" :
+          "``` javascript" :
+          cs b :
+          "```" :
+          "" :
+          []
+
+        responseStr :: Response -> [String]
+        responseStr resp =
+          "**Response**: " :
+          "" :
+          (" - Status code " ++ show (resp ^. respStatus)) :
+          (resp ^. respBody &
+            maybe [" - No response body\n"]
+                  (\b -> " - Response body as below." : jsonStr b))
+
+-- * Instances
+
+-- | The generated docs for @a ':<|>' b@ just appends the docs
+--   for @a@ with the docs for @b@.
+instance (HasDocs layout1, HasDocs layout2)
+      => HasDocs (layout1 :<|> layout2) where
+
+  docsFor Proxy (ep, action) = docsFor p1 (ep, action) <> docsFor p2 (ep, action)
+
+    where p1 :: Proxy layout1
+          p1 = Proxy
+
+          p2 :: Proxy layout2
+          p2 = Proxy
+
+-- | @"books" :> 'Capture' "isbn" Text@ will appear as
+-- @/books/:isbn@ in the docs.
+instance (KnownSymbol sym, ToCapture (Capture sym a), HasDocs sublayout)
+      => HasDocs (Capture sym a :> sublayout) where
+
+  docsFor Proxy (endpoint, action) =
+    docsFor sublayoutP (endpoint', action')
+
+    where sublayoutP = Proxy :: Proxy sublayout
+          captureP = Proxy :: Proxy (Capture sym a)
+
+          action' = over captures (|> toCapture captureP) action
+          endpoint' = over path (\p -> p++"/:"++symbolVal symP) endpoint
+          symP = Proxy :: Proxy sym
+
+
+instance HasDocs Delete where
+  docsFor Proxy (endpoint, action) =
+    single endpoint' action'
+
+    where endpoint' = endpoint & method .~ DocDELETE
+
+          action' = action & response.respBody .~ Nothing
+                           & response.respStatus .~ 204
+
+instance ToSample a => HasDocs (Get a) where
+  docsFor Proxy (endpoint, action) =
+    single endpoint' action'
+
+    where endpoint' = endpoint & method .~ DocGET
+          action' = action & response.respBody .~ sampleByteString p
+          p = Proxy :: Proxy a
+
+instance (KnownSymbol sym, HasDocs sublayout)
+      => HasDocs (Header sym a :> sublayout) where
+  docsFor Proxy (endpoint, action) =
+    docsFor sublayoutP (endpoint, action')
+
+    where sublayoutP = Proxy :: Proxy sublayout
+          action' = over headers (|> headername) action
+          headername = pack $ symbolVal (Proxy :: Proxy sym)
+
+instance ToSample a => HasDocs (Post a) where
+  docsFor Proxy (endpoint, action) =
+    single endpoint' action'
+
+    where endpoint' = endpoint & method .~ DocPOST
+
+          action' = action & response.respBody .~ sampleByteString p
+                           & response.respStatus .~ 201
+
+          p = Proxy :: Proxy a
+
+instance ToSample a => HasDocs (Put a) where
+  docsFor Proxy (endpoint, action) =
+    single endpoint' action'
+
+    where endpoint' = endpoint & method .~ DocPUT
+
+          action' = action & response.respBody .~ sampleByteString p
+                           & response.respStatus .~ 200
+
+          p = Proxy :: Proxy a
+
+
+instance (KnownSymbol sym, ToParam (QueryParam sym a), HasDocs sublayout)
+      => HasDocs (QueryParam sym a :> sublayout) where
+
+  docsFor Proxy (endpoint, action) =
+    docsFor sublayoutP (endpoint, action')
+
+    where sublayoutP = Proxy :: Proxy sublayout
+          paramP = Proxy :: Proxy (QueryParam sym a)
+          action' = over params (|> toParam paramP) action
+
+instance (KnownSymbol sym, ToParam (QueryParams sym a), HasDocs sublayout)
+      => HasDocs (QueryParams sym a :> sublayout) where
+
+  docsFor Proxy (endpoint, action) =
+    docsFor sublayoutP (endpoint, action')
+
+    where sublayoutP = Proxy :: Proxy sublayout
+          paramP = Proxy :: Proxy (QueryParams sym a)
+          action' = over params (|> toParam paramP) action
+
+
+instance (KnownSymbol sym, ToParam (QueryFlag sym), HasDocs sublayout)
+      => HasDocs (QueryFlag sym :> sublayout) where
+
+  docsFor Proxy (endpoint, action) =
+    docsFor sublayoutP (endpoint, action')
+
+    where sublayoutP = Proxy :: Proxy sublayout
+          paramP = Proxy :: Proxy (QueryFlag sym)
+          action' = over params (|> toParam paramP) action
+
+instance HasDocs Raw where
+  docsFor _proxy (endpoint, action) =
+    single endpoint action
+
+instance (ToSample a, HasDocs sublayout)
+      => HasDocs (ReqBody a :> sublayout) where
+
+  docsFor Proxy (endpoint, action) =
+    docsFor sublayoutP (endpoint, action')
+
+    where sublayoutP = Proxy :: Proxy sublayout
+
+          action' = action & rqbody .~ sampleByteString p
+          p = Proxy :: Proxy a
+
+instance (KnownSymbol path, HasDocs sublayout) => HasDocs (path :> sublayout) where
+
+  docsFor Proxy (endpoint, action) =
+    docsFor sublayoutP (endpoint', action)
+
+    where sublayoutP = Proxy :: Proxy sublayout
+          endpoint' = endpoint & path <>~ symbolVal pa
+          pa = Proxy :: Proxy path
+
+{-
+
+-- | Serve your API's docs as markdown embedded in an html \<pre> tag.
+--
+-- > type MyApi = "users" :> Get [User]
+-- >         :<|> "docs   :> Raw
+-- >
+-- > apiProxy :: Proxy MyApi
+-- > apiProxy = Proxy
+-- >
+-- > server :: Server MyApi
+-- > server = listUsers
+-- >     :<|> serveDocumentation apiProxy
+serveDocumentation :: HasDocs api => Proxy api -> Server Raw
+serveDocumentation proxy _request respond =
+  respond $ responseLBS ok200 [] $ cs $ toHtml $ markdown $ docs proxy
+
+toHtml :: String -> String
+toHtml md =
+  "<html>" ++
+  "<body>" ++
+  "<pre>" ++
+  md ++
+  "</pre>" ++
+  "</body>" ++
+  "</html>"
+-}
