diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,12 @@
 [The latest version of this document is on GitHub.](https://github.com/haskell-servant/servant/blob/master/servant-docs/CHANGELOG.md)
 [Changelog for `servant` package contains significant entries for all core packages.](https://github.com/haskell-servant/servant/blob/master/servant/CHANGELOG.md)
 
+0.11.3
+------
+
+- Support `servant-0.15`
+   - Instances for 'Stream' and 'StreamBody'
+
 0.11.2
 ------
 
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2014-2016, Zalora South East Asia Pte Ltd, Servant Contributors
+Copyright (c) 2014-2016, Zalora South East Asia Pte Ltd, 2016-2018 Servant Contributors
 
 All rights reserved.
 
diff --git a/example/greet.hs b/example/greet.hs
--- a/example/greet.hs
+++ b/example/greet.hs
@@ -5,14 +5,15 @@
 {-# LANGUAGE OverloadedStrings     #-}
 {-# LANGUAGE TypeOperators         #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
-import Control.Lens
-import Data.Aeson
-import Data.Proxy
-import Data.String.Conversions
-import Data.Text (Text)
-import GHC.Generics
-import Servant.API
-import Servant.Docs
+import           Control.Lens
+import           Data.Aeson
+import           Data.Proxy
+import           Data.String.Conversions
+import           Data.Text
+                 (Text)
+import           GHC.Generics
+import           Servant.API
+import           Servant.Docs
 
 -- * Example
 
diff --git a/golden/comprehensive.md b/golden/comprehensive.md
new file mode 100644
--- /dev/null
+++ b/golden/comprehensive.md
@@ -0,0 +1,557 @@
+## GET /
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /alternative/left
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /alternative/right
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /capture/:foo
+
+### Captures:
+
+- *foo*: Capture foo Int
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /capture-all/:foo
+
+### Captures:
+
+- *foo*: Capture all foo Int
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /description
+
+### foo
+
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /flag
+
+### GET Parameters:
+
+- foo
+     - **Description**: QueryFlag
+     - This parameter is a **flag**. This means no value is expected to be associated to this parameter.
+
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /foo
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /get-int
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+17
+```
+
+## GET /header
+
+### Headers:
+
+- This endpoint is sensitive to the value of the **foo** HTTP header.
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /header-lenient
+
+### Headers:
+
+- This endpoint is sensitive to the value of the **bar** HTTP header.
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /http-version
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /is-secure
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /named-context
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /param
+
+### GET Parameters:
+
+- foo
+     - **Values**: *1, 2, 3*
+     - **Description**: QueryParams Int
+
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /param-lenient
+
+### GET Parameters:
+
+- bar
+     - **Values**: *1, 2, 3*
+     - **Description**: QueryParams Int
+
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /params
+
+### GET Parameters:
+
+- foo
+     - **Values**: *1, 2, 3*
+     - **Description**: QueryParams Int
+     - This parameter is a **list**. All GET parameters with the name foo[] will forward their values in a list to the handler.
+
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## POST /post-int
+
+### Response:
+
+- Status code 204
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+17
+```
+
+## POST /post-no-content
+
+### Response:
+
+- Status code 204
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /raw
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- No response body
+
+## GET /remote-host
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /req-body
+
+### Request:
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+17
+```
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /req-body-lenient
+
+### Request:
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+17
+```
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /res-headers
+
+### Response:
+
+- Status code 200
+- Headers: [("foo","17")]
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /streaming
+
+### Request:
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- No response body
+
+## GET /summary
+
+### foo
+
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
+## GET /vault
+
+### Response:
+
+- Status code 200
+- Headers: []
+
+- Supported content types are:
+
+    - `application/json;charset=utf-8`
+    - `application/json`
+
+- Example (`application/json;charset=utf-8`, `application/json`):
+
+```javascript
+
+```
+
diff --git a/include/overlapping-compat.h b/include/overlapping-compat.h
deleted file mode 100644
--- a/include/overlapping-compat.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#if __GLASGOW_HASKELL__ >= 710
-#define OVERLAPPABLE_ {-# OVERLAPPABLE #-}
-#define OVERLAPPING_  {-# OVERLAPPING #-}
-#else
-{-# LANGUAGE OverlappingInstances #-}
-#define OVERLAPPABLE_
-#define OVERLAPPING_
-#endif
diff --git a/servant-docs.cabal b/servant-docs.cabal
--- a/servant-docs.cabal
+++ b/servant-docs.cabal
@@ -1,31 +1,35 @@
+cabal-version:       >=1.10
 name:                servant-docs
-version:             0.11.2
+version:             0.11.3
+
 synopsis:            generate API docs for your servant webservice
+category:            Servant, Web
 description:
   Library for generating API docs from a servant API definition.
   .
   Runnable example <https://github.com/haskell-servant/servant/blob/master/servant-docs/example/greet.hs here>.
   .
   <https://github.com/haskell-servant/servant/blob/master/servant-docs/CHANGELOG.md CHANGELOG>
+
+homepage:            http://haskell-servant.readthedocs.org/
+bug-reports:         http://github.com/haskell-servant/servant/issues
 license:             BSD3
 license-file:        LICENSE
 author:              Servant Contributors
 maintainer:          haskell-servant-maintainers@googlegroups.com
-copyright:           2014-2016 Zalora South East Asia Pte Ltd, Servant Contributors
-category:            Servant, Web
+copyright:           2014-2016 Zalora South East Asia Pte Ltd, 2016-2018 Servant Contributors
 build-type:          Simple
-cabal-version:       >=1.10
 tested-with:
-  GHC==7.8.4
-  GHC==7.10.3
-  GHC==8.0.2
-  GHC==8.2.2
-homepage:            http://haskell-servant.readthedocs.org/
-Bug-reports:         http://github.com/haskell-servant/servant/issues
+  GHC ==8.0.2
+   || ==8.2.2
+   || ==8.4.4
+   || ==8.6.2
+
 extra-source-files:
-  include/*.h
   CHANGELOG.md
   README.md
+  golden/comprehensive.md
+
 source-repository head
   type: git
   location: http://github.com/haskell-servant/servant.git
@@ -41,39 +45,32 @@
   --
   -- note: mtl lower bound is so low because of GHC-7.8
   build-depends:
-      base       >= 4.7      && < 4.11
-    , bytestring >= 0.10.4.0 && < 0.11
+      base       >= 4.9      && < 4.13
+    , bytestring >= 0.10.8.1 && < 0.11
     , text       >= 1.2.3.0  && < 1.3
 
-  if !impl(ghc >= 8.0)
-    build-depends:
-      semigroups          >=0.18.3 && <0.19
-
   -- Servant dependencies
   build-depends:
-      servant            == 0.13.*
+      servant            == 0.15.*
 
   -- Other dependencies: Lower bound around what is in the latest Stackage LTS.
   -- Here can be exceptions if we really need features from the newer versions.
   build-depends:
-      aeson                >= 1.2.3.0  && < 1.3
+      aeson                >= 1.4.1.0  && < 1.5
     , aeson-pretty         >= 0.8.5    && < 0.9
-    , base-compat          >= 0.9.3    && < 0.10
-    , case-insensitive     >= 1.2.0.10 && < 1.3
+    , base-compat          >= 0.10.5   && < 0.11
+    , case-insensitive     >= 1.2.0.11 && < 1.3
     , control-monad-omega  >= 0.3.1    && < 0.4
-    , hashable             >= 1.2.6.1  && < 1.3
-    , http-media           >= 0.7.1.1  && < 0.8
-    , http-types           >= 0.12     && < 0.13
-    , lens                 >= 4.15.4   && < 4.17
+    , hashable             >= 1.2.7.0  && < 1.3
+    , http-media           >= 0.7.1.3  && < 0.8
+    , http-types           >= 0.12.2   && < 0.13
+    , lens                 >= 4.17     && < 4.18
     , string-conversions   >= 0.4.0.1  && < 0.5
-    , unordered-containers >= 0.2.8.0  && < 0.3
+    , unordered-containers >= 0.2.9.0  && < 0.3
 
   hs-source-dirs: src
   default-language: Haskell2010
-  ghc-options: -Wall
-  if impl(ghc >= 8.0)
-    ghc-options: -Wno-redundant-constraints
-  include-dirs: include
+  ghc-options: -Wall -Wno-redundant-constraints
 
 executable greet-docs
   main-is: greet.hs
@@ -100,6 +97,7 @@
   -- Dependencies inherited from the library. No need to specify bounds.
   build-depends:
       base
+    , base-compat
     , aeson
     , lens
     , servant
@@ -108,7 +106,8 @@
 
   -- Additonal dependencies
   build-depends:
-      hspec                >= 2.4.4    && < 2.5
+      tasty         >= 1.1.0.4  && < 1.2,
+      tasty-golden  >= 2.3.2    && < 2.4,
+      tasty-hunit   >= 0.10.0.1 && < 0.11,
+      transformers  >= 0.5.2.0  && < 0.6
 
-  build-tool-depends:
-    hspec-discover:hspec-discover >=2.4.4 && <2.5
diff --git a/src/Servant/Docs.hs b/src/Servant/Docs.hs
--- a/src/Servant/Docs.hs
+++ b/src/Servant/Docs.hs
@@ -56,5 +56,5 @@
   , single
   ) where
 
-import Servant.Docs.Internal
-import Servant.Docs.Internal.Pretty
+import           Servant.Docs.Internal
+import           Servant.Docs.Internal.Pretty
diff --git a/src/Servant/Docs/Internal.hs b/src/Servant/Docs/Internal.hs
--- a/src/Servant/Docs/Internal.hs
+++ b/src/Servant/Docs/Internal.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP                    #-}
 {-# LANGUAGE ConstraintKinds        #-}
 {-# LANGUAGE DataKinds              #-}
 {-# LANGUAGE DefaultSignatures      #-}
@@ -17,36 +16,49 @@
 {-# LANGUAGE TypeOperators          #-}
 {-# LANGUAGE UndecidableInstances   #-}
 
-#include "overlapping-compat.h"
 module Servant.Docs.Internal where
 
-import           Prelude                    ()
+import           Prelude ()
 import           Prelude.Compat
 
 import           Control.Applicative
-import           Control.Arrow              (second)
-import           Control.Lens               (makeLenses, mapped, over,
-                                             traversed, view, (%~), (&), (.~),
-                                             (<>~), (^.), (|>))
+import           Control.Arrow
+                 (second)
+import           Control.Lens
+                 (makeLenses, mapped, over, traversed, view, (%~), (&), (.~),
+                 (<>~), (^.), (|>))
 import qualified Control.Monad.Omega        as Omega
 import qualified Data.ByteString.Char8      as BSC
-import           Data.ByteString.Lazy.Char8 (ByteString)
+import           Data.ByteString.Lazy.Char8
+                 (ByteString)
 import qualified Data.CaseInsensitive       as CI
-import           Data.Foldable              (fold)
-import           Data.Hashable              (Hashable)
-import           Data.HashMap.Strict        (HashMap)
-import           Data.List.Compat           (intercalate, intersperse, sort)
-import           Data.List.NonEmpty         (NonEmpty ((:|)), groupWith)
+import           Data.Foldable
+                 (toList)
+import           Data.Foldable
+                 (fold)
+import           Data.Hashable
+                 (Hashable)
+import           Data.HashMap.Strict
+                 (HashMap)
+import           Data.List.Compat
+                 (intercalate, intersperse, sort)
+import           Data.List.NonEmpty
+                 (NonEmpty ((:|)), groupWith)
 import qualified Data.List.NonEmpty         as NE
 import           Data.Maybe
-import           Data.Monoid                (All (..), Any (..), Dual (..),
-                                             First (..), Last (..),
-                                             Product (..), Sum (..))
-import           Data.Ord                   (comparing)
-import           Data.Proxy                 (Proxy (Proxy))
-import           Data.Semigroup             (Semigroup (..))
-import           Data.String.Conversions    (cs)
-import           Data.Text                  (Text, unpack)
+import           Data.Monoid
+                 (All (..), Any (..), Dual (..), First (..), Last (..),
+                 Product (..), Sum (..))
+import           Data.Ord
+                 (comparing)
+import           Data.Proxy
+                 (Proxy (Proxy))
+import           Data.Semigroup
+                 (Semigroup (..))
+import           Data.String.Conversions
+                 (cs)
+import           Data.Text
+                 (Text, unpack)
 import           GHC.Generics
 import           GHC.TypeLits
 import           Servant.API
@@ -64,14 +76,15 @@
 -- 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' '.~' 'HTTP.methodPost'
--- POST /foo
--- @
+-- >>> defEndpoint
+-- "GET" /
+--
+-- >>> defEndpoint & path <>~ ["foo"]
+-- "GET" /foo
+--
+-- >>> defEndpoint & path <>~ ["foo"] & method .~ HTTP.methodPost
+-- "POST" /foo
+--
 data Endpoint = Endpoint
   { _path   :: [String]      -- type collected
   , _method :: HTTP.Method   -- type collected
@@ -92,14 +105,15 @@
 --
 -- Here's how you can modify it:
 --
--- @
--- λ> 'defEndpoint'
--- GET /
--- λ> 'defEndpoint' & 'path' '<>~' ["foo"]
--- GET /foo
--- λ> 'defEndpoint' & 'path' '<>~' ["foo"] & 'method' '.~' 'HTTP.methodPost'
--- POST /foo
--- @
+-- >>> defEndpoint
+-- "GET" /
+--
+-- >>> defEndpoint & path <>~ ["foo"]
+-- "GET" /foo
+--
+-- >>> defEndpoint & path <>~ ["foo"] & method .~ HTTP.methodPost
+-- "POST" /foo
+--
 defEndpoint :: Endpoint
 defEndpoint = Endpoint [] HTTP.methodGet
 
@@ -210,12 +224,14 @@
 -- want to write a 'ToSample' instance for the type that'll be represented
 -- as encoded data in the response.
 --
--- Can be tweaked with three lenses.
+-- Can be tweaked with four lenses.
 --
--- > λ> defResponse
--- > Response {_respStatus = 200, _respTypes = [], _respBody = []}
--- > λ> defResponse & respStatus .~ 204 & respBody .~ [("If everything goes well", "{ \"status\": \"ok\" }")]
--- > Response {_respStatus = 204, _respTypes = [], _respBody = [("If everything goes well", "{ \"status\": \"ok\" }")]}
+-- >>> defResponse
+-- Response {_respStatus = 200, _respTypes = [], _respBody = [], _respHeaders = []}
+--
+-- >>> defResponse & respStatus .~ 204 & respBody .~ [("If everything goes well", "application/json", "{ \"status\": \"ok\" }")]
+-- Response {_respStatus = 204, _respTypes = [], _respBody = [("If everything goes well",application/json,"{ \"status\": \"ok\" }")], _respHeaders = []}
+--
 data Response = Response
   { _respStatus  :: Int
   , _respTypes   :: [M.MediaType]
@@ -225,12 +241,14 @@
 
 -- | Default response: status code 200, no response body.
 --
--- Can be tweaked with two lenses.
+-- Can be tweaked with four lenses.
 --
--- > λ> defResponse
--- > Response {_respStatus = 200, _respBody = Nothing}
--- > λ> defResponse & respStatus .~ 204 & respBody .~ Just "[]"
--- > Response {_respStatus = 204, _respBody = Just "[]"}
+-- >>> defResponse
+-- Response {_respStatus = 200, _respTypes = [], _respBody = [], _respHeaders = []}
+--
+-- >>> defResponse & respStatus .~ 204
+-- Response {_respStatus = 204, _respTypes = [], _respBody = [], _respHeaders = []}
+--
 defResponse :: Response
 defResponse = Response
   { _respStatus  = 200
@@ -276,10 +294,12 @@
 --
 -- Tweakable with lenses.
 --
--- > λ> defAction
--- > Action {_captures = [], _headers = [], _params = [], _mxParams = [], _rqbody = Nothing, _response = Response {_respStatus = 200, _respBody = Nothing}}
--- > λ> defAction & response.respStatus .~ 201
--- > Action {_captures = [], _headers = [], _params = [], _mxParams = [], _rqbody = Nothing, _response = Response {_respStatus = 201, _respBody = Nothing}}
+-- >>> defAction
+-- Action {_authInfo = [], _captures = [], _headers = [], _params = [], _notes = [], _mxParams = [], _rqtypes = [], _rqbody = [], _response = Response {_respStatus = 200, _respTypes = [], _respBody = [], _respHeaders = []}}
+--
+-- >>> defAction & response.respStatus .~ 201
+-- Action {_authInfo = [], _captures = [], _headers = [], _params = [], _notes = [], _mxParams = [], _rqtypes = [], _rqbody = [], _response = Response {_respStatus = 201, _respTypes = [], _respBody = [], _respHeaders = []}}
+--
 defAction :: Action
 defAction =
   Action []
@@ -347,7 +367,8 @@
 -- | Generate the docs for a given API that implements 'HasDocs'. This is the
 -- default way to create documentation.
 --
--- prop> docs == docsWithOptions defaultDocOptions
+-- > docs == docsWithOptions defaultDocOptions
+--
 docs :: HasDocs api => Proxy api -> API
 docs p = docsWithOptions p defaultDocOptions
 
@@ -750,9 +771,9 @@
 
         contentStr mime_type body =
           "" :
-          "    ```" <> markdownForType mime_type :
+          "```" <> markdownForType mime_type :
           cs body :
-          "    ```" :
+          "```" :
           "" :
           []
 
@@ -776,7 +797,7 @@
 
 -- | The generated docs for @a ':<|>' b@ just appends the docs
 --   for @a@ with the docs for @b@.
-instance OVERLAPPABLE_
+instance {-# OVERLAPPABLE #-}
          (HasDocs a, HasDocs b)
       => HasDocs (a :<|> b) where
 
@@ -824,7 +845,7 @@
           symP = Proxy :: Proxy sym
 
 
-instance OVERLAPPABLE_
+instance {-# OVERLAPPABLE #-}
         (ToSample a, AllMimeRender (ct ': cts) a, KnownNat status
         , ReflectMethod method)
     => HasDocs (Verb method status (ct ': cts) a) where
@@ -840,7 +861,25 @@
           status = fromInteger $ natVal (Proxy :: Proxy status)
           p = Proxy :: Proxy a
 
-instance OVERLAPPING_
+-- | TODO: mention the endpoint is streaming, its framing strategy
+--
+-- Also there are no samples.
+--
+-- TODO: AcceptFraming for content-type
+instance {-# OVERLAPPABLE #-}
+        (Accept ct, KnownNat status, ReflectMethod method)
+    => HasDocs (Stream method status framing ct a) where
+  docsFor Proxy (endpoint, action) DocOptions{..} =
+    single endpoint' action'
+
+    where endpoint' = endpoint & method .~ method'
+          action' = action & response.respTypes .~ allMime t
+                           & response.respStatus .~ status
+          t = Proxy :: Proxy '[ct]
+          method' = reflectMethod (Proxy :: Proxy method)
+          status = fromInteger $ natVal (Proxy :: Proxy status)
+
+instance {-# OVERLAPPING #-}
         (ToSample a, AllMimeRender (ct ': cts) a, KnownNat status
         , ReflectMethod method, AllHeaderSamples ls, GetHeaders (HList ls))
     => HasDocs (Verb method status (ct ': cts) (Headers ls a)) where
@@ -930,7 +969,6 @@
 -- both are even defined) for any particular type.
 instance (ToSample a, AllMimeRender (ct ': cts) a, HasDocs api)
       => HasDocs (ReqBody' mods (ct ': cts) a :> api) where
-
   docsFor Proxy (endpoint, action) opts@DocOptions{..} =
     docsFor subApiP (endpoint, action') opts
 
@@ -941,6 +979,18 @@
           t = Proxy :: Proxy (ct ': cts)
           p = Proxy :: Proxy a
 
+-- | TODO: this instance is incomplete.
+instance (HasDocs api, Accept ctype) => HasDocs (StreamBody' mods framing ctype a :> api) where
+    docsFor Proxy (endpoint, action) opts =
+        docsFor subApiP (endpoint, action') opts
+      where
+        subApiP = Proxy :: Proxy api
+
+        action' :: Action
+        action' = action & rqtypes .~ toList (contentTypes t)
+
+        t = Proxy :: Proxy ctype
+
 instance (KnownSymbol path, HasDocs api) => HasDocs (path :> api) where
 
   docsFor Proxy (endpoint, action) =
@@ -1005,3 +1055,6 @@
 instance ToSample a => ToSample (First a)
 instance ToSample a => ToSample (Last a)
 instance ToSample a => ToSample (Dual a)
+
+-- $setup
+-- >>> :set -XOverloadedStrings
diff --git a/src/Servant/Docs/Internal/Pretty.hs b/src/Servant/Docs/Internal/Pretty.hs
--- a/src/Servant/Docs/Internal/Pretty.hs
+++ b/src/Servant/Docs/Internal/Pretty.hs
@@ -4,16 +4,20 @@
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE OverloadedStrings     #-}
 {-# LANGUAGE PolyKinds             #-}
-{-# LANGUAGE TypeOperators         #-}
 {-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE TypeOperators         #-}
 
 module Servant.Docs.Internal.Pretty where
 
-import Data.Aeson               (ToJSON(..))
-import Data.Aeson.Encode.Pretty (encodePretty)
-import Data.Proxy               (Proxy(Proxy))
-import Network.HTTP.Media       ((//))
-import Servant.API
+import           Data.Aeson
+                 (ToJSON (..))
+import           Data.Aeson.Encode.Pretty
+                 (encodePretty)
+import           Data.Proxy
+                 (Proxy (Proxy))
+import           Network.HTTP.Media
+                 ((//))
+import           Servant.API
 
 -- | PrettyJSON content type.
 data PrettyJSON
diff --git a/test/Servant/DocsSpec.hs b/test/Servant/DocsSpec.hs
--- a/test/Servant/DocsSpec.hs
+++ b/test/Servant/DocsSpec.hs
@@ -1,55 +1,69 @@
-{-# LANGUAGE CPP                   #-}
-{-# LANGUAGE DataKinds             #-}
-{-# LANGUAGE DeriveGeneric         #-}
-{-# LANGUAGE FlexibleContexts      #-}
-{-# LANGUAGE FlexibleInstances     #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE OverloadedStrings     #-}
-{-# LANGUAGE TypeOperators         #-}
-{-# LANGUAGE TypeSynonymInstances  #-}
+{-# LANGUAGE DataKinds                  #-}
+{-# LANGUAGE DeriveFunctor              #-}
+{-# LANGUAGE DeriveGeneric              #-}
+{-# LANGUAGE FlexibleContexts           #-}
+{-# LANGUAGE FlexibleInstances          #-}
+{-# LANGUAGE GADTs                      #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses      #-}
+{-# LANGUAGE OverloadedStrings          #-}
+{-# LANGUAGE TypeOperators              #-}
+{-# LANGUAGE TypeSynonymInstances       #-}
 {-# OPTIONS_GHC -fno-warn-orphans  #-}
-#if __GLASGOW_HASKELL__ >= 800
 {-# OPTIONS_GHC -freduction-depth=100 #-}
-#else
-{-# OPTIONS_GHC -fcontext-stack=100 #-}
-#endif
 
 module Servant.DocsSpec where
 
 import           Control.Lens
+                 ((&), (<>~))
+import           Control.Monad
+                 (unless)
+import           Control.Monad.Trans.Writer
+                 (Writer, runWriter, tell)
 import           Data.Aeson
-import           Data.Monoid
+import           Data.List
+                 (isInfixOf)
 import           Data.Proxy
-import           Data.String.Conversions (cs)
+import           Data.String.Conversions
+                 (cs)
 import           GHC.Generics
-import           Test.Hspec
+import           Prelude ()
+import           Prelude.Compat
+import           Test.Tasty
+                 (TestName, TestTree, testGroup)
+import           Test.Tasty.Golden
+                 (goldenVsString)
+import           Test.Tasty.HUnit
+                 (Assertion, HasCallStack, assertFailure, testCase, (@?=))
 
 import           Servant.API
-import           Servant.API.Internal.Test.ComprehensiveAPI
 import           Servant.Docs.Internal
+import           Servant.Test.ComprehensiveAPI
 
 -- * comprehensive api
 
 -- This declaration simply checks that all instances are in place.
-_ = docs comprehensiveAPI
+comprehensiveDocs :: API
+comprehensiveDocs = docs comprehensiveAPI
 
 instance ToParam (QueryParam' mods "foo" Int) where
-  toParam = error "unused"
+  toParam _ = DocQueryParam "foo" ["1","2","3"] "QueryParams Int" Normal
 instance ToParam (QueryParam' mods "bar" Int) where
-  toParam = error "unused"
+  toParam _ = DocQueryParam "bar" ["1","2","3"] "QueryParams Int" Normal
 instance ToParam (QueryParams "foo" Int) where
-  toParam = error "unused"
+  toParam _ = DocQueryParam "foo" ["1","2","3"] "QueryParams Int" List
 instance ToParam (QueryFlag "foo") where
-  toParam = error "unused"
+  toParam _ = DocQueryParam "foo" [] "QueryFlag" Flag
 instance ToCapture (Capture "foo" Int) where
-  toCapture = error "unused"
+  toCapture _ = DocCapture "foo" "Capture foo Int"
 instance ToCapture (CaptureAll "foo" Int) where
-  toCapture = error "unused"
+  toCapture _ = DocCapture "foo" "Capture all foo Int"
 
 -- * specs
 
-spec :: Spec
+spec :: TestTree
 spec = describe "Servant.Docs" $ do
+  golden "comprehensive API" "golden/comprehensive.md" (markdown comprehensiveDocs)
 
   describe "markdown" $ do
     let md = markdown (docs (Proxy :: Proxy TestApi1))
@@ -150,3 +164,42 @@
 
 instance ToSample UT where
   toSamples _ = [("yks", UT1), ("kaks", UT2)]
+
+-------------------------------------------------------------------------------
+-- HSpec like DSL for tasty
+-------------------------------------------------------------------------------
+
+newtype TestTreeM a = TestTreeM (Writer [TestTree] a)
+  deriving (Functor, Applicative, Monad)
+
+runTestTreeM :: TestTreeM () -> [TestTree]
+runTestTreeM (TestTreeM m) = snd (runWriter m)
+
+class Describe r where
+    describe :: TestName -> TestTreeM () -> r
+
+instance a ~ () =>  Describe (TestTreeM a) where
+    describe n t = TestTreeM $ tell [ describe n t ]
+
+instance Describe TestTree where
+    describe n t = testGroup n $ runTestTreeM t
+
+it :: TestName -> Assertion -> TestTreeM ()
+it n assertion = TestTreeM $ tell [ testCase n assertion ]
+
+shouldBe :: (Eq a, Show a, HasCallStack) => a -> a -> Assertion
+shouldBe = (@?=)
+
+shouldContain :: (Eq a, Show a, HasCallStack) => [a] -> [a] -> Assertion
+shouldContain = compareWith (flip isInfixOf) "does not contain"
+
+shouldNotContain :: (Eq a, Show a, HasCallStack) => [a] -> [a] -> Assertion
+shouldNotContain = compareWith (\x y -> not (isInfixOf y x)) "contains"
+
+compareWith :: (Show a, Show b, HasCallStack) => (a -> b -> Bool) -> String -> a -> b -> Assertion
+compareWith f msg x y = unless (f x y) $ assertFailure $
+    show x ++ " " ++ msg ++ " " ++ show y
+
+golden :: TestName -> FilePath -> String -> TestTreeM ()
+golden n fp contents = TestTreeM $ tell
+    [ goldenVsString n fp (return (cs contents)) ]
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -1,1 +1,8 @@
-{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+module Main (main) where
+
+import           Test.Tasty
+                 (defaultMain)
+import qualified Servant.DocsSpec
+
+main :: IO ()
+main = defaultMain Servant.DocsSpec.spec
