diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+0.6.0.0
+-------
+
+* PR #49. Migrate to elm-bridge and http 2.0.0
+
 0.5.0.0
 -------
 * Fix generation for APIs with response headers.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -16,16 +16,15 @@
 
 ```haskell
 {-# LANGUAGE DataKinds         #-}
-{-# LANGUAGE DeriveGeneric     #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TemplateHaskell   #-}
 {-# LANGUAGE TypeOperators     #-}
 
-import           Elm          (Spec (Spec), specsToDir, toElmDecoderSource,
-                               toElmTypeSource)
-import           GHC.Generics (Generic)
+import           Elm.Derive   (defaultOptions, deriveBoth)
+
 import           Servant.API  ((:>), Capture, Get, JSON)
-import           Servant.Elm  (ElmType, Proxy (Proxy), defElmImports,
-                               generateElmForAPI)
+import           Servant.Elm  (DefineElm (DefineElm), Proxy (Proxy), defElmImports, defElmOptions,
+                               generateElmModuleWith)
 ```
 
 We have some Haskell-defined types and our Servant API.
@@ -33,9 +32,9 @@
 ```haskell
 data Book = Book
     { name :: String
-    } deriving (Generic)
+    }
 
-instance ElmType Book
+deriveBoth defaultOptions ''Book
 
 type BooksApi = "books" :> Capture "bookId" Int :> Get '[JSON] Book
 ```
@@ -43,15 +42,18 @@
 Now we can generate Elm functions to query the API:
 
 ```haskell
-spec :: Spec
-spec = Spec ["Generated", "MyApi"]
-            (defElmImports
-             : toElmTypeSource    (Proxy :: Proxy Book)
-             : toElmDecoderSource (Proxy :: Proxy Book)
-             : generateElmForAPI  (Proxy :: Proxy BooksApi))
-
 main :: IO ()
-main = specsToDir [spec] "my-elm-dir"
+main =
+  generateElmModuleWith
+    defElmOptions
+    [ "Generated"
+    , "MyApi"
+    ]
+    defElmImports
+    "my-elm-dir"
+    [ DefineElm (Proxy :: Proxy Book)
+    ]
+    (Proxy :: Proxy BooksApi)
 ```
 
 Let's save this as `example.hs` and run it:
@@ -65,46 +67,69 @@
 Here's what was generated:
 
 ```elm
-module Generated.MyApi exposing (..)
+module Generated.MyApi exposing(..)
 
-import Json.Decode exposing (..)
-import Json.Decode.Pipeline exposing (..)
-import Json.Encode
+import Json.Decode
+import Json.Encode exposing (Value)
+-- The following module comes from bartavelle/json-helpers
+import Json.Helpers exposing (..)
+import Dict exposing (Dict)
+import Set
 import Http
 import String
+import Url.Builder
 
+maybeBoolToIntStr : Maybe Bool -> String
+maybeBoolToIntStr mx =
+  case mx of
+    Nothing -> ""
+    Just True -> "1"
+    Just False -> "0"
 
-type alias Book =
-    { name : String
-    }
+type alias Book  =
+   { name: String
+   }
 
-decodeBook : Decoder Book
-decodeBook =
-    decode Book
-        |> required "name" string
+jsonDecBook : Json.Decode.Decoder ( Book )
+jsonDecBook =
+   Json.Decode.succeed (\pname -> {name = pname})
+   |> required "name" (Json.Decode.string)
 
-getBooksByBookId : Int -> Http.Request (Book)
+jsonEncBook : Book -> Value
+jsonEncBook  val =
+   Json.Encode.object
+   [ ("name", Json.Encode.string val.name)
+   ]
+
+
+getBooksByBookId : Int -> Http.Request Book
 getBooksByBookId capture_bookId =
-    Http.request
-        { method =
-            "GET"
-        , headers =
-            []
-        , url =
-            String.join "/"
-                [ ""
-                , "books"
-                , capture_bookId |> toString |> Http.encodeUri
-                ]
-        , body =
-            Http.emptyBody
-        , expect =
-            Http.expectJson decodeBook
-        , timeout =
-            Nothing
-        , withCredentials =
-            False
-        }
+    let
+        params =
+            List.filterMap identity
+            (List.concat
+                [])
+    in
+        Http.request
+            { method =
+                "GET"
+            , headers =
+                []
+            , url =
+                Url.Builder.absolute
+                    [ "books"
+                    , capture_bookId |> String.fromInt
+                    ]
+                    params
+            , body =
+                Http.emptyBody
+            , expect =
+                Http.expectJson <| jsonDecBook
+            , timeout =
+                Nothing
+            , withCredentials =
+                False
+            }
 ```
 
 See [`examples`](examples) for a complete usage example, or take a look at
diff --git a/examples/books/generate.hs b/examples/books/generate.hs
--- a/examples/books/generate.hs
+++ b/examples/books/generate.hs
@@ -1,21 +1,19 @@
 {-# LANGUAGE DataKinds         #-}
-{-# LANGUAGE DeriveGeneric     #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TemplateHaskell   #-}
 {-# LANGUAGE TypeOperators     #-}
 
-import           Elm          (Spec (Spec), specsToDir, toElmDecoderSource,
-                               toElmEncoderSource, toElmTypeSource)
-import           GHC.Generics (Generic)
 import           Servant.API  ((:<|>), (:>), Capture, Get, JSON, Post, ReqBody)
-import           Servant.Elm  (ElmOptions (..), ElmType, Proxy (Proxy),
-                               UrlPrefix (Static), defElmImports, defElmOptions,
-                               generateElmForAPIWith)
+import           Servant.Elm  (DefineElm (DefineElm), ElmOptions(urlPrefix),
+                               Proxy (Proxy), UrlPrefix(Static), defaultOptions,
+                               defElmImports, defElmOptions, deriveBoth,
+                               generateElmModuleWith)
 
 data Book = Book
   { name :: String
-  } deriving (Show, Eq, Generic)
+  } deriving (Show, Eq)
 
-instance ElmType Book
+deriveBoth defaultOptions ''Book
 
 type BooksApi = "books" :> ReqBody '[JSON] Book :> Post '[JSON] Book
            :<|> "books" :> Get '[JSON] [Book]
@@ -24,13 +22,15 @@
 myElmOpts :: ElmOptions
 myElmOpts = defElmOptions { urlPrefix = Static "http://localhost:8000" }
 
-spec :: Spec
-spec = Spec ["Generated", "BooksApi"]
-            (defElmImports
-             : toElmTypeSource    (Proxy :: Proxy Book)
-             : toElmDecoderSource (Proxy :: Proxy Book)
-             : toElmEncoderSource (Proxy :: Proxy Book)
-             : generateElmForAPIWith myElmOpts (Proxy :: Proxy BooksApi))
-
 main :: IO ()
-main = specsToDir [spec] "elm"
+main =
+  generateElmModuleWith
+    myElmOpts
+    [ "Generated"
+    , "BooksApi"
+    ]
+    defElmImports
+    "elm"
+    [ DefineElm (Proxy :: Proxy Book)
+    ]
+    (Proxy :: Proxy BooksApi)
diff --git a/examples/e2e-tests/generate.hs b/examples/e2e-tests/generate.hs
--- a/examples/e2e-tests/generate.hs
+++ b/examples/e2e-tests/generate.hs
@@ -1,18 +1,13 @@
 {-# LANGUAGE DataKinds         #-}
-{-# LANGUAGE DeriveAnyClass    #-}
-{-# LANGUAGE DeriveGeneric     #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TemplateHaskell   #-}
 {-# LANGUAGE TypeOperators     #-}
 
-import           Elm          (Spec (Spec), specsToDir, toElmDecoderSource,
-                               toElmEncoderSource, toElmTypeSource)
-import           GHC.Generics (Generic)
 import           Servant.API  ((:<|>), (:>), Capture, Get, GetNoContent, JSON,
-                               NoContent, Post, QueryParam, ReqBody)
-import           Servant.Elm  (ElmOptions (..), ElmType, Proxy (Proxy),
-                               UrlPrefix (Static), defElmImports, defElmOptions,
-                               generateElmForAPIWith)
-
+                               Post, QueryParam, ReqBody)
+import           Servant.Elm  (DefineElm (DefineElm), ElmOptions(..), Proxy (Proxy),
+                               UrlPrefix (Static), defaultOptions, defElmImports,
+                               defElmOptions, deriveBoth, generateElmModuleWith)
 
 myElmOpts :: ElmOptions
 myElmOpts = defElmOptions { urlPrefix = Static "https://httpbin.org" }
@@ -20,31 +15,30 @@
 
 data MessageBody = MessageBody
   { message :: String }
-  deriving (Generic, ElmType)
 
 data QueryArgs = QueryArgs
   { q :: String }
-  deriving (Generic, ElmType)
 
 data Response  = Response
   { origin :: String }
-  deriving (Generic, ElmType)
 
 data ResponseWithJson  = ResponseWithJson
   { json :: MessageBody }
-  deriving (Generic, ElmType)
 
 data ResponseWithArgs  = ResponseWithArgs
   { args :: QueryArgs }
-  deriving (Generic, ElmType)
 
+concat <$> mapM
+  (deriveBoth defaultOptions)
+  [''MessageBody, ''QueryArgs, ''Response, ''ResponseWithJson, ''ResponseWithArgs]
 
+
 type Api
      = "ip"
     :> Get '[JSON] Response
   :<|> "status"
     :> "204"
-    :> GetNoContent '[JSON] NoContent
+    :> GetNoContent '[JSON] ()
   :<|> "post"
     :> ReqBody '[JSON] MessageBody
     :> Post '[JSON] ResponseWithJson
@@ -55,26 +49,19 @@
     :> Get '[JSON] Response
 
 
-spec :: Spec
-spec =
-  Spec ["Generated", "Api"]
-    (defElmImports
-     : toElmTypeSource    (Proxy :: Proxy Response)
-     : toElmDecoderSource (Proxy :: Proxy Response)
-     : toElmTypeSource    (Proxy :: Proxy NoContent)
-     : toElmTypeSource    (Proxy :: Proxy MessageBody)
-     : toElmEncoderSource (Proxy :: Proxy MessageBody)
-     : toElmDecoderSource (Proxy :: Proxy MessageBody)
-     : toElmTypeSource    (Proxy :: Proxy ResponseWithJson)
-     : toElmDecoderSource (Proxy :: Proxy ResponseWithJson)
-     : toElmTypeSource    (Proxy :: Proxy QueryArgs)
-     : toElmDecoderSource (Proxy :: Proxy QueryArgs)
-     : toElmTypeSource    (Proxy :: Proxy ResponseWithArgs)
-     : toElmDecoderSource (Proxy :: Proxy ResponseWithArgs)
-     : generateElmForAPIWith
-         myElmOpts
-         (Proxy :: Proxy Api))
-
-
 main :: IO ()
-main = specsToDir [spec] "elm"
+main =
+  generateElmModuleWith
+    myElmOpts
+    [ "Generated"
+    , "Api"
+    ]
+    defElmImports
+    "elm"
+    [ DefineElm (Proxy :: Proxy MessageBody)
+    , DefineElm (Proxy :: Proxy QueryArgs)
+    , DefineElm (Proxy :: Proxy Response)
+    , DefineElm (Proxy :: Proxy ResponseWithJson)
+    , DefineElm (Proxy :: Proxy ResponseWithArgs)
+    ]
+    (Proxy :: Proxy Api)
diff --git a/examples/giphy/generate.hs b/examples/giphy/generate.hs
--- a/examples/giphy/generate.hs
+++ b/examples/giphy/generate.hs
@@ -1,62 +1,54 @@
 {-# LANGUAGE DataKinds         #-}
-{-# LANGUAGE DeriveGeneric     #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TemplateHaskell   #-}
 {-# LANGUAGE TypeOperators     #-}
 
-import qualified Data.Text    as T
-import           Elm          (Options, Spec (Spec), defaultOptions,
-                               fieldLabelModifier, specsToDir,
-                               toElmDecoderSourceWith, toElmTypeSourceWith)
-import           GHC.Generics (Generic)
+import qualified Elm.Derive as Elm
+
 import           Servant.API  ((:>), Get, JSON, QueryParam)
-import           Servant.Elm  (ElmOptions (..), ElmType, Proxy (Proxy), UrlPrefix(Static),
-                               defElmImports, defElmOptions,
-                               generateElmForAPIWith)
+import           Servant.Elm  (DefineElm (DefineElm), ElmOptions (urlPrefix),
+                               Proxy (Proxy), UrlPrefix (Static), defElmImports,
+                               defElmOptions, defaultOptions, deriveBoth,
+                               generateElmModuleWith)
 
 data GifData = GifData
   { image_url :: String
-  } deriving (Show, Eq, Generic)
+  } deriving (Show, Eq)
 
 data Gif = Gif
   { _data :: GifData
-  } deriving (Show, Eq, Generic)
-
-instance ElmType GifData
-instance ElmType Gif
-
-stripUnderscore :: T.Text -> T.Text
-stripUnderscore field =
-  if T.head field == '_' then
-    T.tail field
-  else
-    field
+  } deriving (Show, Eq)
 
-options :: Elm.Options
-options =
-  Elm.defaultOptions
-    { Elm.fieldLabelModifier = stripUnderscore }
+concat <$> mapM
+  (deriveBoth defaultOptions
+    { Elm.fieldLabelModifier = \ field ->
+        if head field == '_' then
+          tail field
+        else
+          field
+    , Elm.unwrapUnaryRecords = False
+    }
+  ) [''GifData, ''Gif]
 
 myElmOpts :: ElmOptions
 myElmOpts =
   defElmOptions
     { urlPrefix =
         Static "http://api.giphy.com/v1/gifs"
-    , elmExportOptions =
-        options
     }
 
 type GiphyApi = "random" :> QueryParam "api_key" String :> QueryParam "tag" String :> Get '[JSON] Gif
 
-giphySpec :: Spec
-giphySpec = Spec ["Generated", "GiphyApi"]
-                 (defElmImports
-                  : toElmTypeSourceWith    options (Proxy :: Proxy Gif)
-                  : toElmTypeSourceWith    options (Proxy :: Proxy GifData)
-                  : toElmDecoderSourceWith options (Proxy :: Proxy Gif)
-                  : toElmDecoderSourceWith options (Proxy :: Proxy GifData)
-                  : generateElmForAPIWith
-                      myElmOpts
-                      (Proxy :: Proxy GiphyApi))
-
 main :: IO ()
-main = specsToDir [giphySpec] "elm"
+main =
+  generateElmModuleWith
+    myElmOpts
+    [ "Generated"
+    , "GiphyApi"
+    ]
+    defElmImports
+    "elm"
+    [ DefineElm (Proxy :: Proxy Gif)
+    , DefineElm (Proxy :: Proxy GifData)
+    ]
+    (Proxy :: Proxy GiphyApi)
diff --git a/examples/readme-example/generate.hs b/examples/readme-example/generate.hs
--- a/examples/readme-example/generate.hs
+++ b/examples/readme-example/generate.hs
@@ -1,29 +1,30 @@
 {-# LANGUAGE DataKinds         #-}
-{-# LANGUAGE DeriveGeneric     #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TemplateHaskell   #-}
 {-# LANGUAGE TypeOperators     #-}
 
-import           Elm          (Spec (Spec), specsToDir, toElmDecoderSource,
-                               toElmTypeSource)
-import           GHC.Generics (Generic)
 import           Servant.API  ((:>), Capture, Get, JSON)
-import           Servant.Elm  (ElmType, Proxy (Proxy), defElmImports,
-                               generateElmForAPI)
+import           Servant.Elm  (DefineElm (DefineElm), Proxy (Proxy),
+                               defaultOptions, defElmImports, defElmOptions,
+                               deriveBoth, generateElmModuleWith)
 
 data Book = Book
-    { name :: String
-    } deriving ((Generic))
+  { name :: String
+  }
 
-instance ElmType Book
+deriveBoth defaultOptions ''Book
 
 type BooksApi = "books" :> Capture "bookId" Int :> Get '[JSON] Book
 
-spec :: Spec
-spec = Spec ["Generated", "MyApi"]
-            (defElmImports
-             : toElmTypeSource    (Proxy :: Proxy Book)
-             : toElmDecoderSource (Proxy :: Proxy Book)
-             : generateElmForAPI  (Proxy :: Proxy BooksApi))
-
 main :: IO ()
-main = specsToDir [spec] "my-elm-dir"
+main =
+  generateElmModuleWith
+    defElmOptions
+    [ "Generated"
+    , "MyApi"
+    ]
+    defElmImports
+    "my-elm-dir"
+    [ DefineElm (Proxy :: Proxy Book)
+    ]
+    (Proxy :: Proxy BooksApi)
diff --git a/servant-elm.cabal b/servant-elm.cabal
--- a/servant-elm.cabal
+++ b/servant-elm.cabal
@@ -1,5 +1,5 @@
 name:                servant-elm
-version:             0.5.0.0
+version:             0.6.0.0
 synopsis:            Automatically derive Elm functions to query servant webservices.
 description:         Please see README.md
 homepage:            http://github.com/mattjbray/servant-elm#readme
@@ -13,7 +13,7 @@
 extra-source-files:
   CHANGELOG.md
   README.md
-  test/elm-sources/elm-package.json
+  test/elm-sources/elm.json
   test/elm-sources/*.elm
 cabal-version:       >=1.10
 
@@ -30,9 +30,11 @@
   exposed-modules:     Servant.Elm
                      , Servant.Elm.Internal.Foreign
                      , Servant.Elm.Internal.Generate
-                     , Servant.Elm.Internal.Orphans
+                     , Servant.Elm.Internal.Options
   build-depends:       base >= 4.7 && < 5
-                     , elm-export      >= 0.5
+                     , aeson >= 0.9
+                     , directory
+                     , elm-bridge      >= 0.4
                      , lens
                      , servant         >= 0.8
                      , servant-foreign >= 0.8
@@ -51,9 +53,10 @@
                      , HUnit
                      , aeson >= 0.9
                      , base
-                     , elm-export      >= 0.5
+                     , elm-bridge >= 0.4
                      , hspec
                      , servant
+                     , servant-client
                      , servant-elm
                      , text
   ghc-options:         -threaded -rtsopts -with-rtsopts=-N -Wall
@@ -69,7 +72,7 @@
   build-depends:       aeson >= 0.9
                       , base
                       , directory
-                      , elm-export      >= 0.5
+                      , elm-bridge >= 0.4
                       , hspec
                       , interpolate
                       , mockery
@@ -77,6 +80,7 @@
                       , servant
                       , servant-elm
                       , text
+                      , typed-process
   ghc-options:         -threaded -rtsopts -with-rtsopts=-N -Wall
   default-language:    Haskell2010
 
@@ -89,7 +93,7 @@
     Buildable:         False
   main-is:             generate.hs
   build-depends:       base >= 4.7 && < 5
-                     , elm-export      >= 0.5
+                     , elm-bridge >= 0.4
                      , servant >= 0.8
                      , servant-elm
   hs-source-dirs:      examples/books
@@ -101,7 +105,7 @@
     Buildable:         False
   main-is:             generate.hs
   build-depends:       base >= 4.7 && < 5
-                     , elm-export      >= 0.5
+                     , elm-bridge >= 0.4
                      , servant >= 0.8
                      , servant-elm
   hs-source-dirs:      examples/e2e-tests
@@ -113,7 +117,7 @@
     Buildable:         False
   main-is:             generate.hs
   build-depends:       base >= 4.7 && < 5
-                     , elm-export >= 0.5
+                     , elm-bridge >= 0.4
                      , servant >= 0.8
                      , servant-elm
                      , text
@@ -126,7 +130,7 @@
     Buildable:         False
   main-is:             generate.hs
   build-depends:       base >= 4.7 && < 5
-                     , elm-export >= 0.5
+                     , elm-bridge >= 0.4
                      , servant >= 0.8
                      , servant-elm
   hs-source-dirs:      examples/readme-example
diff --git a/src/Servant/Elm.hs b/src/Servant/Elm.hs
--- a/src/Servant/Elm.hs
+++ b/src/Servant/Elm.hs
@@ -14,14 +14,20 @@
 module Servant.Elm
        ( generateElmForAPI
        , generateElmForAPIWith
+       , generateElmModule
+       , generateElmModuleWith
        , ElmOptions(..)
        , UrlPrefix(..)
        , defElmOptions
        , defElmImports
+       , defaultOptions
        -- * Convenience re-exports from the "Elm" module
-       , Spec(Spec)
-       , ElmType
-       , specsToDir
+       , DefineElm (..)
+       , EType (..)
+       , defaultTypeAlterations
+       , toElmType
+       , deriveBoth
+       , deriveElmDef
        -- * Convenience re-exports from "Data.Proxy"
        , Proxy(Proxy)
        ) where
@@ -29,8 +35,11 @@
 import           Servant.Elm.Internal.Generate (ElmOptions (..), UrlPrefix (..),
                                                 defElmImports, defElmOptions,
                                                 generateElmForAPI,
-                                                generateElmForAPIWith)
-
+                                                generateElmForAPIWith,
+                                                generateElmModule,
+                                                generateElmModuleWith)
+import           Servant.Elm.Internal.Options  (defaultOptions)
 import           Data.Proxy                    (Proxy (Proxy))
-import           Elm                           (ElmType, Spec (Spec),
-                                                specsToDir)
+import           Elm.TyRep                     (EType (..), toElmType)
+import           Elm.Module                    (DefineElm (..), defaultTypeAlterations)
+import           Elm.Derive                    (deriveBoth, deriveElmDef)
diff --git a/src/Servant/Elm/Internal/Foreign.hs b/src/Servant/Elm/Internal/Foreign.hs
--- a/src/Servant/Elm/Internal/Foreign.hs
+++ b/src/Servant/Elm/Internal/Foreign.hs
@@ -7,21 +7,27 @@
 module Servant.Elm.Internal.Foreign where
 
 import           Data.Proxy      (Proxy (Proxy))
-import           Elm             (ElmDatatype, ElmType, toElmType)
+import           Data.Typeable   (Typeable)
+import           Elm.TyRep       (EType, toElmType)
+import           Servant.API     (Headers(..))
 import           Servant.Foreign (Foreign, GenerateList, HasForeign,
                                   HasForeignType, Req, listFromAPI, typeFor)
 
 
 data LangElm
 
-instance (ElmType a) => HasForeignType LangElm ElmDatatype a where
-  typeFor _ _ _ =
-    toElmType (Proxy :: Proxy a)
+--- TODO: Generate Elm functions that can handle the response headers. PRs
+--- welcome!
+instance {-# OVERLAPPING #-} (Typeable a) => HasForeignType LangElm EType (Headers b a) where
+  typeFor _ _ _ = toElmType (Proxy :: Proxy a)
 
+instance {-# OVERLAPPABLE #-} (Typeable a) => HasForeignType LangElm EType a where
+  typeFor _ _ _ = toElmType (Proxy :: Proxy a)
+
 getEndpoints
-  :: ( HasForeign LangElm ElmDatatype api
-     , GenerateList ElmDatatype (Foreign ElmDatatype api))
+  :: ( HasForeign LangElm EType api
+     , GenerateList EType (Foreign EType api))
   => Proxy api
-  -> [Req ElmDatatype]
+  -> [Req EType]
 getEndpoints =
-  listFromAPI (Proxy :: Proxy LangElm) (Proxy :: Proxy ElmDatatype)
+  listFromAPI (Proxy :: Proxy LangElm) (Proxy :: Proxy EType)
diff --git a/src/Servant/Elm/Internal/Generate.hs b/src/Servant/Elm/Internal/Generate.hs
--- a/src/Servant/Elm/Internal/Generate.hs
+++ b/src/Servant/Elm/Internal/Generate.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE RecordWildCards       #-}
 {-# LANGUAGE FlexibleContexts      #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE OverloadedStrings     #-}
@@ -5,22 +6,36 @@
 
 import           Prelude                      hiding ((<$>))
 import           Control.Lens                 (to, (^.))
-import           Data.List                    (nub)
+import           Data.List                    (intercalate, intersperse, nub)
 import           Data.Maybe                   (catMaybes)
-import           Data.Proxy                   (Proxy)
+import           Data.Proxy                   (Proxy(..))
 import           Data.Text                    (Text)
 import qualified Data.Text                    as T
 import qualified Data.Text.Lazy               as L
 import qualified Data.Text.Encoding           as T
-import           Elm                          (ElmDatatype(..), ElmPrimitive(..))
-import qualified Elm
-import           Servant.API                  (NoContent (..))
+import           Data.Text.IO                 as TIO
+
+import           Elm.Json (jsonParserForType, jsonSerForType)
+import qualified Elm.Module                   as Elm
+import           Elm.TyRep (ETCon(..), EType(..), ETypeDef(..), toElmType)
+import           Elm.TyRender (renderElm)
+import           Elm.Versions (ElmVersion(Elm0p18))
+
 import           Servant.Elm.Internal.Foreign (LangElm, getEndpoints)
-import           Servant.Elm.Internal.Orphans ()
 import qualified Servant.Foreign              as F
+import           System.Directory (createDirectoryIfMissing)
 import           Text.PrettyPrint.Leijen.Text
 
 
+toElmTypeRefWith :: ElmOptions -> EType -> Text
+toElmTypeRefWith ElmOptions{..} = T.pack . renderElm . elmTypeAlterations
+
+toElmDecoderRefWith :: ElmOptions -> EType -> Text
+toElmDecoderRefWith ElmOptions{..} = T.pack . jsonParserForType . elmTypeAlterations
+
+toElmEncoderRefWith :: ElmOptions -> EType -> Text
+toElmEncoderRefWith ElmOptions{..} = T.pack . jsonSerForType . elmTypeAlterations
+
 {-|
 Options to configure how code is generated.
 -}
@@ -34,11 +49,13 @@
     argument.
     -}
     urlPrefix             :: UrlPrefix
-  , elmExportOptions      :: Elm.Options
-    -- ^ Options to pass to elm-export
-  , emptyResponseElmTypes :: [ElmDatatype]
+  , elmTypeAlterations        :: (EType -> EType)
+    -- ^ Alterations to perform on ETypes before code generation.
+  , elmAlterations        :: (ETypeDef -> ETypeDef)
+    -- ^ Alterations to perform on ETypeDefs before code generation.
+  , emptyResponseElmTypes :: [EType]
     -- ^ Types that represent an empty Http response.
-  , stringElmTypes        :: [ElmDatatype]
+  , stringElmTypes        :: [EType]
     -- ^ Types that represent a String.
   }
 
@@ -47,6 +64,7 @@
   = Static T.Text
   | Dynamic
 
+type Namespace = [String]
 
 {-|
 Default options for generating Elm code.
@@ -55,25 +73,26 @@
 
 > { urlPrefix =
 >     Static ""
-> , elmExportOptions =
->     Elm.defaultOptions
+> , elmAlterations =
+>     Elm.defaultTypeAlterations
 > , emptyResponseElmTypes =
->     [ toElmType NoContent ]
+>     [ getType (Proxy :: Proxy ()) ]
 > , stringElmTypes =
->     [ toElmType "" ]
+>     [ getType (Proxy :: Proxy String)
+>     , getType (Proxy :: Proxy T.Text) ]
 > }
 -}
 defElmOptions :: ElmOptions
 defElmOptions = ElmOptions
   { urlPrefix = Static ""
-  , elmExportOptions = Elm.defaultOptions
+  , elmTypeAlterations = Elm.defaultTypeAlterations
+  , elmAlterations = Elm.defaultAlterations
   , emptyResponseElmTypes =
-      [ Elm.toElmType NoContent
-      , Elm.toElmType ()
+      [ toElmType (Proxy :: Proxy ())
       ]
   , stringElmTypes =
-      [ Elm.toElmType ("" :: String)
-      , Elm.toElmType ("" :: T.Text)
+      [ toElmType (Proxy :: Proxy String)
+      , toElmType (Proxy :: Proxy T.Text)
       ]
   }
 
@@ -85,24 +104,84 @@
 
 The default required imports are:
 
-> import Json.Decode exposing (..)
-> import Json.Decode.Pipeline exposing (..)
-> import Json.Encode
+> import Json.Decode
+> import Json.Encode exposing (Value)
+> -- The following module comes from bartavelle/json-helpers
+> import Json.Helpers exposing (..)
+> import Dict exposing (Dict)
+> import Set
 > import Http
 > import String
+> import Url.Builder
 -}
 defElmImports :: Text
 defElmImports =
   T.unlines
-    [ "import Json.Decode exposing (..)"
-    , "import Json.Decode.Pipeline exposing (..)"
-    , "import Json.Encode"
+    [ "import Json.Decode"
+    , "import Json.Encode exposing (Value)"
+    , "-- The following module comes from bartavelle/json-helpers"
+    , "import Json.Helpers exposing (..)"
+    , "import Dict exposing (Dict)"
+    , "import Set"
     , "import Http"
     , "import String"
+    , "import Url.Builder"
+    , ""
+    , "maybeBoolToIntStr : Maybe Bool -> String"
+    , "maybeBoolToIntStr mx ="
+    , "  case mx of"
+    , "    Nothing -> \"\""
+    , "    Just True -> \"1\""
+    , "    Just False -> \"0\""
     ]
 
+{-|
+Helper to generate a complete Elm module given a list of Elm type definitions
+and an API.
+-}
+generateElmModuleWith ::
+     ( F.HasForeign LangElm EType api
+     , F.GenerateList EType (F.Foreign EType api)
+     )
+  => ElmOptions
+  -> Namespace
+  -> Text
+  -> FilePath
+  -> [Elm.DefineElm]
+  -> Proxy api
+  -> IO ()
+generateElmModuleWith options namespace imports rootDir typeDefs api = do
+  let out =
+        T.unlines $
+        [ T.pack $ Elm.moduleHeader Elm0p18 moduleName
+        , ""
+        , imports
+        , T.pack $ Elm.makeModuleContentWithAlterations (elmAlterations options) typeDefs
+        ] ++
+        generateElmForAPIWith options api
+      moduleName = intercalate "." namespace
+      filePath = intercalate "/" $ rootDir:init namespace
+      fileName = intercalate "/" $ filePath:[last namespace ++ ".elm"]
+  createDirectoryIfMissing True filePath
+  TIO.writeFile fileName out
 
 {-|
+Calls generateElmModuleWith with @defElmOptions@.
+-}
+generateElmModule ::
+     ( F.HasForeign LangElm EType api
+     , F.GenerateList EType (F.Foreign EType api)
+     )
+  => Namespace
+  -> Text
+  -> FilePath
+  -> [Elm.DefineElm]
+  -> Proxy api
+  -> IO ()
+generateElmModule namespace imports filePath typeDefs api =
+  generateElmModuleWith defElmOptions namespace imports filePath typeDefs api
+
+{-|
 Generate Elm code for the API with default options.
 
 Returns a list of Elm functions to query your Servant API from Elm.
@@ -112,8 +191,8 @@
 which handles the module name for you.
 -}
 generateElmForAPI
-  :: ( F.HasForeign LangElm ElmDatatype api
-     , F.GenerateList ElmDatatype (F.Foreign ElmDatatype api))
+  :: ( F.HasForeign LangElm EType api
+     , F.GenerateList EType (F.Foreign EType api))
   => Proxy api
   -> [Text]
 generateElmForAPI =
@@ -124,12 +203,12 @@
 Generate Elm code for the API with custom options.
 -}
 generateElmForAPIWith
-  :: ( F.HasForeign LangElm ElmDatatype api
-     , F.GenerateList ElmDatatype (F.Foreign ElmDatatype api))
+  :: ( F.HasForeign LangElm EType api
+     , F.GenerateList EType (F.Foreign EType api))
   => ElmOptions
   -> Proxy api
   -> [Text]
-generateElmForAPIWith opts =
+generateElmForAPIWith opts = intersperse "" .
   nub . map docToText . map (generateElmForRequest opts) . getEndpoints
 
 i :: Int
@@ -138,7 +217,7 @@
 {-|
 Generate an Elm function for one endpoint.
 -}
-generateElmForRequest :: ElmOptions -> F.Req ElmDatatype -> Doc
+generateElmForRequest :: ElmOptions -> F.Req EType -> Doc
 generateElmForRequest opts request =
   funcDef
   where
@@ -159,8 +238,10 @@
         ]
 
     fnName =
-      request ^. F.reqFuncName . to (T.replace "-" "" . F.camelCase) . to stext
+      request ^. F.reqFuncName . to (replace . F.camelCase) . to stext
 
+    replace = T.replace "-" "" . T.replace "." ""
+
     typeSignature =
       mkTypeSignature opts request
 
@@ -174,14 +255,14 @@
       mkRequest opts request
 
 
-mkTypeSignature :: ElmOptions -> F.Req ElmDatatype -> Doc
+mkTypeSignature :: ElmOptions -> F.Req EType -> Doc
 mkTypeSignature opts request =
   (hsep . punctuate " ->" . concat)
     [ catMaybes [urlPrefixType]
     , headerTypes
     , urlCaptureTypes
     , queryTypes
-    , catMaybes [bodyType, returnType]
+    , catMaybes [bodyType, toMsgType, returnType]
     ]
   where
     urlPrefixType :: Maybe Doc
@@ -190,9 +271,9 @@
           Dynamic -> Just "String"
           Static _ -> Nothing
 
-    elmTypeRef :: ElmDatatype -> Doc
+    elmTypeRef :: EType -> Doc
     elmTypeRef eType =
-      stext (Elm.toElmTypeRefWith (elmExportOptions opts) eType)
+      stext (toElmTypeRefWith opts eType)
 
     headerTypes :: [Doc]
     headerTypes =
@@ -218,25 +299,31 @@
     bodyType =
         fmap elmTypeRef $ request ^. F.reqBody
 
+    toMsgType :: Maybe Doc
+    toMsgType = do
+      result <- fmap elmTypeRef $ request ^. F.reqReturnType
+      Just ("(Result Http.Error " <+> parens result <+> " -> msg)")
+
     returnType :: Maybe Doc
     returnType = do
-      result <- fmap elmTypeRef $ request ^. F.reqReturnType
-      pure ("Http.Request" <+> parens result)
+      pure ("Cmd msg")
 
 
-elmHeaderArg :: F.HeaderArg ElmDatatype -> Doc
+elmHeaderArg :: F.HeaderArg EType -> Doc
 elmHeaderArg header =
   "header_" <>
   header ^. F.headerArg . F.argName . to (stext . T.replace "-" "_" . F.unPathSegment)
 
 
-elmCaptureArg :: F.Segment ElmDatatype -> Doc
+elmCaptureArg :: F.Segment EType -> Doc
 elmCaptureArg segment =
   "capture_" <>
-  F.captureArg segment ^. F.argName . to (stext . F.unPathSegment)
+  F.captureArg segment ^. F.argName . to (stext . replace . F.unPathSegment)
+  where
+    replace = T.replace "-" "_"
 
 
-elmQueryArg :: F.QueryArg ElmDatatype -> Doc
+elmQueryArg :: F.QueryArg EType -> Doc
 elmQueryArg arg =
   "query_" <>
   arg ^. F.queryArgName . F.argName . to (stext . F.unPathSegment)
@@ -257,7 +344,7 @@
 
 mkArgs
   :: ElmOptions
-  -> F.Req ElmDatatype
+  -> F.Req EType
   -> Doc
 mkArgs opts request =
   (hsep . concat) $
@@ -281,22 +368,21 @@
       ]
     , -- Request body
       maybe [] (const [elmBodyArg]) (request ^. F.reqBody)
+    , pure "toMsg"
     ]
 
 
-mkLetParams :: ElmOptions -> F.Req ElmDatatype -> Maybe Doc
+mkLetParams :: ElmOptions -> F.Req EType -> Maybe Doc
 mkLetParams opts request =
-  if null (request ^. F.reqUrl . F.queryStr) then
-    Nothing
-  else
     Just $ "params =" <$>
-           indent i ("List.filter (not << String.isEmpty)" <$>
-                      indent i (elmList params))
+           indent i ("List.filterMap identity" <$>
+                      parens ("List.concat" <$>
+                              indent i (elmList params)))
   where
     params :: [Doc]
     params = map paramToDoc (request ^. F.reqUrl . F.queryStr)
 
-    paramToDoc :: F.QueryArg ElmDatatype -> Doc
+    paramToDoc :: F.QueryArg EType -> Doc
     paramToDoc qarg =
       -- something wrong with indentation here...
       case qarg ^. F.queryArgType of
@@ -309,28 +395,44 @@
               if isElmStringType opts argType || isElmMaybeStringType opts argType then
                 ""
               else
-                "toString >> "
+                "String.fromInt >> "
           in
-              (if wrapped then name else "Just" <+> name) <$>
-              indent 4 ("|> Maybe.map" <+> parens (toStringSrc <> "Http.encodeUri >> (++)" <+> dquotes (elmName <> equals)) <$>
-                        "|> Maybe.withDefault" <+> dquotes empty)
+              "[" <+> (if wrapped then elmName else "Just" <+> elmName) <> line <>
+                (indent 4 ("|> Maybe.map" <+> parens (toStringSrc <> "Url.Builder.string" <+> dquotes elmName)))
+                <+> "]"
+              -- (if wrapped then name else "Just" <+> name) <$>
+              -- indent 4 ("|> Maybe.map" <+> parens (toStringSrc <> "Http.encodeUri >> (++)" <+> dquotes (elmName <> equals)) <$>
+              --           "|> Maybe.withDefault" <+> dquotes empty)
 
         F.Flag ->
-            "if" <+> name <+> "then" <$>
-            indent 4 (dquotes (name <> equals)) <$>
+            "[" <+>
+            ("if" <+> elmName <+> "then" <$>
+            indent 4 ("Just" <+> parens ("Url.Builder.string" <+> dquotes name <+> dquotes empty)) <$>
             indent 2 "else" <$>
-            indent 4 (dquotes empty)
+            indent 4 "Nothing")
+            <+> "]"
 
         F.List ->
-            name <$>
-            indent 4 ("|> List.map" <+> parens (backslash <> "val ->" <+> dquotes (name <> "[]=") <+> "++ (val |> toString |> Http.encodeUri)") <$>
-                      "|> String.join" <+> dquotes "&")
+            let
+              argType = qarg ^. F.queryArgName . F.argType
+              convertedVal =
+                if isElmListOfMaybeBoolType argType then
+                  parens ("maybeBoolToIntStr" <+> "val")
+                else
+                  "val"
+            in
+            elmName <$>
+            indent 4 ("|> List.map"
+                      <+> parens (backslash <> "val ->" <+> "Just"
+                                  <+> parens ("Url.Builder.string"
+                                              <+> dquotes (name <> "[]")
+                                              <+> convertedVal)))
       where
-        name = elmQueryArg qarg
-        elmName= qarg ^. F.queryArgName . F.argName . to (stext . F.unPathSegment)
+        elmName = elmQueryArg qarg
+        name = qarg ^. F.queryArgName . F.argName . to (stext . F.unPathSegment)
 
 
-mkRequest :: ElmOptions -> F.Req ElmDatatype -> Doc
+mkRequest :: ElmOptions -> F.Req EType -> Doc
 mkRequest opts request =
   "Http.request" <$>
   indent i
@@ -348,8 +450,8 @@
          indent i expect
        , "timeout =" <$>
          indent i "Nothing"
-       , "withCredentials =" <$>
-         indent i "False"
+       , "tracker =" <$>
+         indent i "Nothing"
        ])
   where
     method =
@@ -364,7 +466,7 @@
             if isElmMaybeStringType opts argType || isElmStringType opts argType then
               mempty
             else
-              " << toString"
+              " << String.fromInt"
       in
         "Maybe.map" <+> parens (("Http.header" <+> dquotes headerName <> toStringSrc))
         <+>
@@ -388,42 +490,69 @@
         Just elmTypeExpr ->
           let
             encoderName =
-              Elm.toElmEncoderRefWith (elmExportOptions opts) elmTypeExpr
+              toElmEncoderRefWith opts elmTypeExpr
           in
             "Http.jsonBody" <+> parens (stext encoderName <+> elmBodyArg)
 
     expect =
       case request ^. F.reqReturnType of
-        Just elmTypeExpr | isEmptyType opts elmTypeExpr ->
-          let elmConstructor =
-                Elm.toElmTypeRefWith (elmExportOptions opts) elmTypeExpr
-          in
-            "Http.expectStringResponse" <$>
-            indent i (parens (backslash <> braces " body " <+> "->" <$>
-                              indent i ("if String.isEmpty body then" <$>
-                                        indent i "Ok" <+> stext elmConstructor <$>
-                                        "else" <$>
-                                        indent i ("Err" <+> dquotes "Expected the response body to be empty")) <> line))
+        Just elmTypeExpr
+          | isEmptyType opts elmTypeExpr
+            -- let elmConstructor = T.pack (renderElm elmTypeExpr)
+           ->
+            "Http.expectString " <> line <+> indent i "(\\x -> case x of" <> line <+>
+            indent i "Err e -> toMsg (Err e)" <> line <+>
+            indent i "Ok _ -> toMsg (Ok ()))"
+        Just elmTypeExpr ->
+          "Http.expectJson toMsg" <+> renderDecoderName elmTypeExpr
+        Nothing -> error "mkHttpRequest: no reqReturnType?"
+      -- case request ^. F.reqReturnType of
+      --   Just elmTypeExpr | isEmptyType opts elmTypeExpr ->
+      --     let elmConstructor =
+      --           toElmTypeRefWith opts elmTypeExpr
+      --     in
+      --       "Http.expectStringResponse" <$>
+      --       indent i (parens (backslash <> " rsp " <+> "->" <$>
+      --                         indent i ("if String.isEmpty rsp.body then" <$>
+      --                                   indent i "Ok" <+> stext elmConstructor <$>
+      --                                   "else" <$>
+      --                                   indent i ("Err" <+> dquotes "Expected the response body to be empty")) <> line))
 
 
-        Just elmTypeExpr ->
-          "Http.expectJson" <+> stext (Elm.toElmDecoderRefWith (elmExportOptions opts) elmTypeExpr)
+      --   Just elmTypeExpr ->
+      --     "Http.expectJson <|" <+> stext (toElmDecoderRefWith opts elmTypeExpr)
 
-        Nothing ->
-          error "mkHttpRequest: no reqReturnType?"
+      --   Nothing ->
+      --     error "mkHttpRequest: no reqReturnType?"
 
+renderDecoderName :: EType -> Doc
+renderDecoderName elmTypeExpr =
+  case elmTypeExpr of
+    ETyApp (ETyCon (ETCon "List")) t ->
+      parens ("Json.Decode.list " <> parens (renderDecoderName t))
+    ETyApp (ETyCon (ETCon "Maybe")) t ->
+      parens ("Json.Decode.maybe " <> parens (renderDecoderName t))
+    ETyCon (ETCon "Int") -> "Json.Decode.int"
+    ETyCon (ETCon "String") -> "Json.Decode.string"
+    _ -> ("jsonDec" <> stext (T.pack (renderElm elmTypeExpr)))
 
-mkUrl :: ElmOptions -> [F.Segment ElmDatatype] -> Doc
+
+mkUrl :: ElmOptions -> [F.Segment EType] -> Doc
 mkUrl opts segments =
-  "String.join" <+> dquotes "/" <$>
-  (indent i . elmList)
-    ( case urlPrefix opts of
-        Dynamic -> "urlBase"
-        Static url -> dquotes (stext url)
-      : map segmentToDoc segments)
+  urlBuilder <$>
+    (indent i . elmList)
+    ( map segmentToDoc segments)
+  -- ( case urlPrefix opts of
+  --     Dynamic -> "urlBase"
+  --     Static url -> dquotes (stext url)
+  --   : map segmentToDoc segments)
   where
+    urlBuilder :: Doc
+    urlBuilder = case urlPrefix opts of
+      Dynamic -> "Url.Builder.absolute" :: Doc
+      Static url -> "Url.Builder.crossOrigin" <+> dquotes (stext url)
 
-    segmentToDoc :: F.Segment ElmDatatype -> Doc
+    segmentToDoc :: F.Segment EType -> Doc
     segmentToDoc s =
       case F.unSegment s of
         F.Static path ->
@@ -435,28 +564,25 @@
               if isElmStringType opts (arg ^. F.argType) then
                 empty
               else
-                " |> toString"
+                " |> String.fromInt"
           in
-            (elmCaptureArg s) <> toStringSrc <> " |> Http.encodeUri"
+            (elmCaptureArg s) <> toStringSrc
 
 
 mkQueryParams
-  :: F.Req ElmDatatype
+  :: F.Req EType
   -> Doc
-mkQueryParams request =
-  if null (request ^. F.reqUrl . F.queryStr) then
-    empty
-  else
-    line <> "++" <+> align ("if List.isEmpty params then" <$>
-                            indent i (dquotes empty) <$>
-                            "else" <$>
-                            indent i (dquotes "?" <+> "++ String.join" <+> dquotes "&" <+> "params"))
+mkQueryParams _request =
+  -- if null (request ^. F.reqUrl . F.queryStr) then
+  --   empty
+  -- else
+    line <> indent 4 (align "params")
 
 
 {- | Determines whether we construct an Elm function that expects an empty
 response body.
 -}
-isEmptyType :: ElmOptions -> ElmDatatype -> Bool
+isEmptyType :: ElmOptions -> EType -> Bool
 isEmptyType opts elmTypeExpr =
   elmTypeExpr `elem` emptyResponseElmTypes opts
 
@@ -464,20 +590,25 @@
 {- | Determines whether we call `toString` on URL captures and query params of
 this type in Elm.
 -}
-isElmStringType :: ElmOptions -> ElmDatatype -> Bool
+isElmStringType :: ElmOptions -> EType -> Bool
 isElmStringType opts elmTypeExpr =
   elmTypeExpr `elem` stringElmTypes opts
 
 {- | Determines whether a type is 'Maybe a' where 'a' is something akin to a 'String'.
 -}
-isElmMaybeStringType :: ElmOptions -> ElmDatatype -> Bool
-isElmMaybeStringType opts (ElmPrimitive (EMaybe elmTypeExpr)) = elmTypeExpr `elem` stringElmTypes opts
+isElmMaybeStringType :: ElmOptions -> EType -> Bool
+isElmMaybeStringType opts (ETyApp (ETyCon (ETCon "Maybe")) elmTypeExpr) = elmTypeExpr `elem` stringElmTypes opts
 isElmMaybeStringType _ _ = False
 
-isElmMaybeType :: ElmDatatype -> Bool
-isElmMaybeType (ElmPrimitive (EMaybe _)) = True
+isElmMaybeType :: EType -> Bool
+isElmMaybeType (ETyApp (ETyCon (ETCon "Maybe")) _) = True
 isElmMaybeType _ = False
 
+isElmListOfMaybeBoolType :: EType -> Bool
+isElmListOfMaybeBoolType t =
+  case t of
+    (ETyApp (ETyCon (ETCon "List")) (ETyApp (ETyCon (ETCon "Maybe")) (ETyCon (ETCon "Bool")))) -> True
+    _ -> False
 
 -- Doc helpers
 
diff --git a/src/Servant/Elm/Internal/Options.hs b/src/Servant/Elm/Internal/Options.hs
new file mode 100644
--- /dev/null
+++ b/src/Servant/Elm/Internal/Options.hs
@@ -0,0 +1,8 @@
+module Servant.Elm.Internal.Options where
+
+import qualified Data.Aeson as A
+import qualified Elm.Derive as E
+
+defaultOptions :: A.Options
+defaultOptions = E.defaultOptions { A.unwrapUnaryRecords = False}
+
diff --git a/src/Servant/Elm/Internal/Orphans.hs b/src/Servant/Elm/Internal/Orphans.hs
deleted file mode 100644
--- a/src/Servant/Elm/Internal/Orphans.hs
+++ /dev/null
@@ -1,21 +0,0 @@
-{-# LANGUAGE DeriveGeneric      #-}
-{-# LANGUAGE StandaloneDeriving #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-
-module Servant.Elm.Internal.Orphans where
-
-import           Elm         (ElmDatatype, ElmType, toElmType)
-import           Servant.API (NoContent, Headers, getResponse)
-
-
-instance ElmType ElmDatatype where
-  toElmType = id
-
-
-instance ElmType NoContent
-
-
--- TODO: Generate Elm functions that can handle the response headers. PRs
--- welcome!
-instance (ElmType a) => ElmType (Headers ls a) where
-  toElmType = toElmType . getResponse
diff --git a/test/Common.hs b/test/Common.hs
--- a/test/Common.hs
+++ b/test/Common.hs
@@ -1,24 +1,21 @@
 {-# LANGUAGE DataKinds     #-}
-{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE TypeOperators #-}
 module Common where
 
-import           Data.Aeson   (ToJSON)
 import           Data.Proxy   (Proxy (Proxy))
 import           Data.Text    (Text)
-import           Elm          (ElmType)
-import           GHC.Generics (Generic)
 import           Servant.API  ((:<|>), (:>), Capture, Get, GetNoContent, Header,
-                               Header', Headers, JSON, NoContent, Post,
+                               Header', Headers, JSON, Post,
                                PostNoContent, Put, QueryFlag, QueryParam,
                                QueryParam', QueryParams, ReqBody, Required)
+import           Servant.Elm  (deriveBoth, defaultOptions)
 
 data Book = Book
     { title :: String
-    } deriving (Generic)
+    }
 
-instance ToJSON Book
-instance ElmType Book
+deriveBoth defaultOptions ''Book
 
 type TestApi =
        "one"
@@ -41,9 +38,9 @@
          :> Get '[JSON] [Book]
   :<|> "books"
          :> ReqBody '[JSON] Book
-         :> PostNoContent '[JSON] NoContent
+         :> PostNoContent '[JSON] ()
   :<|> "nothing"
-         :> GetNoContent '[JSON] NoContent
+         :> GetNoContent '[JSON] ()
   :<|> "nothing"
          :> Put '[JSON] () -- old way to specify no content
   :<|> "with-a-header"
diff --git a/test/CompileSpec.hs b/test/CompileSpec.hs
--- a/test/CompileSpec.hs
+++ b/test/CompileSpec.hs
@@ -8,23 +8,23 @@
 
 import           Control.Exception
 import           Control.Monad                (when)
+import           Data.List                    (intercalate)
 import           Data.String.Interpolate
 import           Data.String.Interpolate.Util
-import qualified Data.Text                    as T
-import qualified Data.Text.IO                 as T
-import           Elm                          (toElmDecoderSource,
-                                               toElmEncoderSource,
-                                               toElmTypeSource)
-import           Servant.API                  (NoContent)
+import           Elm.Versions (ElmVersion(..))
 import           Servant.Elm
 import           System.Directory             (canonicalizePath,
                                                createDirectoryIfMissing,
                                                doesDirectoryExist,
                                                getCurrentDirectory, removeFile,
                                                setCurrentDirectory)
-import           System.Process
+import           System.Process (callCommand)
+import           System.Process.Typed
+import qualified Data.Text as T
+import qualified Elm.Module                   as Elm
+import           Data.Text.IO                 as TIO
 
-import Common (Book, testApi)
+import Common (Book, TestApi)
 
 main :: IO ()
 main =
@@ -35,23 +35,50 @@
   describe "generateElmForAPI" $ do
     it "creates compilable javascript" $ do
       inTempElmDir $ do
-        let generated =
-              T.intercalate "\n\n" $
-                defElmImports :
-                [ toElmTypeSource (Proxy :: Proxy NoContent)
-                , toElmTypeSource (Proxy :: Proxy Book)
-                , toElmDecoderSource (Proxy :: Proxy Book)
-                , toElmEncoderSource (Proxy :: Proxy Book)
-                ] ++
-                generateElmForAPI testApi
-        T.writeFile "Api.elm" generated
-        callCommand "elm-make Api.elm --output api.js"
+        let options = defElmOptions
+            namespace :: [String]
+            namespace = ["Generated", "BooksApi"]
+            imports = defElmImports
+            rootDir = "."
+            typeDefs = [ DefineElm (Proxy :: Proxy Book)
+                       ]
+            api = (Proxy :: Proxy TestApi)
+        let out =
+              T.unlines $
+              [ T.pack $ Elm.moduleHeader Elm0p18 moduleName
+              , ""
+              , imports
+              , ""
+              , "type NoContent = NoContent"
+              , ""
+              , T.pack $ Elm.makeModuleContentWithAlterations (elmAlterations options) typeDefs
+              ] ++
+              generateElmForAPIWith options api
+            moduleName = T.unpack (T.intercalate "." (map T.pack namespace))
+            filePath = intercalate "/" $ rootDir:init namespace
+            fileName = intercalate "/" $ filePath : [last namespace ++ ".elm"]
+        createDirectoryIfMissing True filePath
+        TIO.writeFile fileName out
 
+        -- generateElmModuleWith
+        --   defElmOptions
+        --   ["Generated", "BooksApi"]
+        --   defElmImports
+        --   "."
+        --   [ DefineElm (Proxy :: Proxy Book)
+        --   , DefineElm (Proxy :: Proxy NoContent)
+        --   ]
+        --   (Proxy :: Proxy TestApi)
+        -- -- Useful for locally checking out sources in your tmp dir
+        callCommand "cp -r . /home/kb/tmp/servelmtest"
+        runProcess_ "elm make Generated/BooksApi.elm --output api.js"
+
+
 inTempElmDir :: IO a -> IO a
 inTempElmDir action = do
+  callCommand "rm -rf ./_test-cache"
   cacheExists <- doesDirectoryExist "_test-cache"
-  when (not cacheExists)
-    createCache
+  when (not cacheExists) createCache
   cacheDir <- canonicalizePath "_test-cache"
   inTempDirectory $ do
     callCommand ("cp -r " ++ cacheDir ++ "/* .")
@@ -61,32 +88,44 @@
 createCache = do
   createDirectoryIfMissing True "_test-cache"
   withCurrentDirectory "_test-cache" $ do
-    writeFile "elm-package.json" $ unindent $ [i|
+    TIO.writeFile "elm.json" $ T.pack $ unindent $ [i|
       {
-          "version": "1.0.0",
-          "summary": "helpful summary of your project, less than 80 characters",
-          "repository": "https://github.com/user/project.git",
-          "license": "BSD3",
+          "type": "application",
           "source-directories": [
               "."
           ],
-          "exposed-modules": [],
+          "elm-version": "0.19.0",
+          "version": "1.0.0",
+          "summary": "helpful summary of your project, less than 80 characters",
           "dependencies": {
-              "elm-lang/core": "5.0.0 <= v < 6.0.0",
-              "elm-community/json-extra": "2.0.0 <= v < 3.0.0",
-              "elm-lang/http": "1.0.0 <= v < 2.0.0",
-              "NoRedInk/elm-decode-pipeline": "3.0.0 <= v < 4.0.0"
+              "direct": {
+                "elm/core": "1.0.2",
+                "elm/json": "1.1.3",
+                "elm/http": "2.0.0",
+                "elm/url": "1.0.0",
+                "bartavelle/json-helpers": "2.0.2"
+              },
+              "indirect": {
+                 "elm/bytes": "1.0.8",
+                 "elm/file": "1.0.5",
+                 "elm/time": "1.0.0"
+              }
           },
-          "elm-version": "0.18.0 <= v < 0.19.0"
+          "test-dependencies": {
+            "direct": {},
+            "indirect": {}
+          }
       }
     |]
-    callCommand "elm-package install --yes"
-    compileDependencies
+    -- callCommand "elm install"
+    -- compileDependencies
 
 compileDependencies :: IO ()
 compileDependencies = do
-  writeFile "Main.elm" "foo = 42"
-  callCommand "elm-make Main.elm --output main.js"
+  TIO.writeFile "Main.elm" "module Main exposing (foo)\n\nfoo : Int\nfoo = 42\n"
+  callCommand "echo '>>>>>> Main.elm'"
+  callCommand "cat Main.elm"
+  callCommand "elm make Main.elm --output main.js"
   removeFile "Main.elm"
   removeFile "main.js"
 
diff --git a/test/GenerateSpec.hs b/test/GenerateSpec.hs
--- a/test/GenerateSpec.hs
+++ b/test/GenerateSpec.hs
@@ -15,7 +15,7 @@
 import           Servant.API               ((:>), Get, JSON)
 import           Servant.Elm
 import           Test.Hspec                (Spec, describe, hspec, it)
-import           Test.HUnit                (Assertion, assertBool)
+import           Test.HUnit                (Assertion, assertEqual)
 
 import           Common                    (testApi)
 
@@ -35,40 +35,78 @@
                           [ ( "test/elm-sources/getOneSource.elm"
                             , "module GetOneSource exposing (..)\n\n" <>
                               "import Http\n" <>
-                              "import Json.Decode exposing (..)\n\n\n")
+                              "import Json.Decode exposing (..)\n" <>
+                              "import Url.Builder\n\n\n"
+                            )
                           , ( "test/elm-sources/postTwoSource.elm"
                             , "module PostTwoSource exposing (..)\n\n" <>
                               "import Http\n" <>
                               "import Json.Decode exposing (..)\n" <>
-                              "import Json.Encode\n\n\n")
+                              "import Json.Encode\n" <>
+                              "import Url.Builder\n\n\n"
+                            )
                           , ( "test/elm-sources/getBooksByIdSource.elm"
                             , "module GetBooksByIdSource exposing (..)\n\n" <>
-                              "import Http\n\n\n")
+                              "import Http\n" <>
+                              "import Url.Builder\n" <>
+                              "import Json.Decode\n" <>
+                              "\n" <>
+                              "type Book = Book\n" <>
+                              "jsonDecBook : Json.Decode.Decoder Book\n" <>
+                              "jsonDecBook = Debug.todo \"\"\n\n"
+                            )
                           , ( "test/elm-sources/getBooksByTitleSource.elm"
                             , "module GetBooksByTitleSource exposing (..)\n\n" <>
-                              "import Http\n\n\n")
+                              "import Http\n" <>
+                              "import Url.Builder\n" <>
+                              "import Json.Decode as J\n\n" <>
+                              "type alias Book = {}\n" <>
+                              "jsonDecBook = J.succeed {}\n\n"
+                            )
                           , ( "test/elm-sources/getBooksSource.elm"
                             , "module GetBooksSource exposing (..)\n\n" <>
                               "import Http\n" <>
-                              "import Json.Decode exposing (..)\n\n\n")
+                              "import Json.Decode exposing (..)\n" <>
+                              "import Url.Builder\n" <>
+                              "import Json.Decode as J\n\n" <>
+                              "type alias Book = {}\n\n" <>
+                              "maybeBoolToIntStr : Maybe Bool -> String\n" <>
+                              "maybeBoolToIntStr mx =\n" <>
+                              "  case mx of\n" <>
+                              "    Nothing -> \"\"\n" <>
+                              "    Just True -> \"1\"\n" <>
+                              "    Just False -> \"0\"\n\n" <>
+                              "jsonDecBook = J.succeed {}\n\n"
+                            )
                           , ( "test/elm-sources/postBooksSource.elm"
                             , "module PostBooksSource exposing (..)\n\n" <>
-                              "import Http\n\n\n")
+                              "import Http\n" <>
+                              "import Url.Builder\n" <>
+                              "import Json.Encode as Enc\n\n" <>
+                              "type alias Book = {}\n" <>
+                              "jsonEncBook = \\b -> Enc.object []\n\n"
+                            )
                           , ( "test/elm-sources/getNothingSource.elm"
                             , "module GetNothingSource exposing (..)\n\n" <>
-                              "import Http\n\n\n")
+                              "import Http\n" <>
+                              "import Url.Builder\n\n\n"
+                            )
                           , ( "test/elm-sources/putNothingSource.elm"
                             , "module PutNothingSource exposing (..)\n\n" <>
-                              "import Http\n\n\n")
+                              "import Http\n" <>
+                              "import Url.Builder\n\n\n"
+                            )
                           , ( "test/elm-sources/getWithaheaderSource.elm"
                             , "module GetWithAHeaderSource exposing (..)\n\n" <>
                               "import Http\n" <>
+                              "import Url.Builder\n" <>
                               "import Json.Decode exposing (..)\n\n\n")
                           , ( "test/elm-sources/getWitharesponseheaderSource.elm"
                             , "module GetWithAResponseHeaderSource exposing (..)\n\n" <>
                               "import Http\n" <>
+                              "import Url.Builder\n" <>
                               "import Json.Decode exposing (..)\n\n\n")]
-                  let generated = map (<> "\n") (generateElmForAPI testApi)
+                  let generated = filter (not . T.null) (generateElmForAPI testApi)
                   generated `itemsShouldBe` expected
            it "with dynamic URLs" $
                do expected <-
@@ -79,6 +117,7 @@
                           [ ( "test/elm-sources/getOneWithDynamicUrlSource.elm"
                             , "module GetOneWithDynamicUrlSource exposing (..)\n\n" <>
                               "import Http\n" <>
+                              "import Url.Builder\n" <>
                               "import Json.Decode exposing (..)\n\n\n")]
                   let generated =
                           map
@@ -99,10 +138,13 @@
 
 shouldBeDiff :: Text -> (String, Text, Text) -> Assertion
 shouldBeDiff a (fpath,header,b) =
-    assertBool
+    assertEqual
         ("< generated\n" <> "> " <> fpath <> "\n" <>
          Diff.ppDiff
              (Diff.getGroupedDiff
-                  (lines (T.unpack (header <> a)))
-                  (lines (T.unpack b))))
-        (header <> a == b)
+                  (lines (T.unpack actual))
+                  (lines (T.unpack expected))))
+        actual expected
+    where
+      actual = T.strip $ header <> a
+      expected = T.strip b
diff --git a/test/elm-sources/elm-package.json b/test/elm-sources/elm-package.json
deleted file mode 100644
--- a/test/elm-sources/elm-package.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-    "version": "1.0.0",
-    "summary": "helpful summary of your project, less than 80 characters",
-    "repository": "https://github.com/user/project.git",
-    "license": "BSD3",
-    "source-directories": [
-        "."
-    ],
-    "exposed-modules": [],
-    "dependencies": {
-        "elm-lang/core": "5.0.0 <= v < 6.0.0",
-        "elm-lang/html": "2.0.0 <= v < 3.0.0",
-        "elm-lang/http": "1.0.0 <= v < 2.0.0"
-    },
-    "elm-version": "0.18.0 <= v < 0.19.0"
-}
diff --git a/test/elm-sources/elm.json b/test/elm-sources/elm.json
new file mode 100644
--- /dev/null
+++ b/test/elm-sources/elm.json
@@ -0,0 +1,30 @@
+{
+    "type": "application",
+    "version": "1.0.0",
+    "summary": "helpful summary of your project, less than 80 characters",
+    "repository": "https://github.com/user/project.git",
+    "license": "BSD3",
+    "source-directories": [
+        "."
+    ],
+    "exposed-modules": [],
+    "dependencies": {
+        "direct": {
+          "elm/core": "1.0.2",
+          "elm/json": "1.1.3",
+          "elm/http": "2.0.0",
+          "elm/url": "1.0.0",
+          "bartavelle/json-helpers": "2.0.2"
+        },
+        "indirect": {
+           "elm/bytes": "1.0.8",
+           "elm/file": "1.0.5",
+           "elm/time": "1.0.0"
+        }
+    },
+    "test-dependencies": {
+      "direct": {},
+      "indirect": {}
+    },
+    "elm-version": "0.19.0"
+}
diff --git a/test/elm-sources/getBooksByIdSource.elm b/test/elm-sources/getBooksByIdSource.elm
--- a/test/elm-sources/getBooksByIdSource.elm
+++ b/test/elm-sources/getBooksByIdSource.elm
@@ -1,27 +1,38 @@
 module GetBooksByIdSource exposing (..)
 
 import Http
+import Url.Builder
+import Json.Decode
 
+type Book = Book
+jsonDecBook : Json.Decode.Decoder Book
+jsonDecBook = Debug.todo ""
 
-getBooksById : Int -> Http.Request (Book)
-getBooksById capture_id =
-    Http.request
-        { method =
-            "GET"
-        , headers =
-            []
-        , url =
-            String.join "/"
-                [ ""
-                , "books"
-                , capture_id |> toString |> Http.encodeUri
-                ]
-        , body =
-            Http.emptyBody
-        , expect =
-            Http.expectJson decodeBook
-        , timeout =
-            Nothing
-        , withCredentials =
-            False
-        }
+getBooksById : Int -> (Result Http.Error  (Book)  -> msg) -> Cmd msg
+getBooksById capture_id toMsg =
+    let
+        params =
+            List.filterMap identity
+            (List.concat
+                [])
+    in
+        Http.request
+            { method =
+                "GET"
+            , headers =
+                []
+            , url =
+                Url.Builder.crossOrigin ""
+                    [ "books"
+                    , capture_id |> String.fromInt
+                    ]
+                    params
+            , body =
+                Http.emptyBody
+            , expect =
+                Http.expectJson toMsg jsonDecBook
+            , timeout =
+                Nothing
+            , tracker =
+                Nothing
+            }
diff --git a/test/elm-sources/getBooksByTitleSource.elm b/test/elm-sources/getBooksByTitleSource.elm
--- a/test/elm-sources/getBooksByTitleSource.elm
+++ b/test/elm-sources/getBooksByTitleSource.elm
@@ -1,27 +1,37 @@
 module GetBooksByTitleSource exposing (..)
 
 import Http
+import Url.Builder
+import Json.Decode as J
 
+type alias Book = {}
+jsonDecBook = J.succeed {}
 
-getBooksByTitle : String -> Http.Request (Book)
-getBooksByTitle capture_title =
-    Http.request
-        { method =
-            "GET"
-        , headers =
-            []
-        , url =
-            String.join "/"
-                [ ""
-                , "books"
-                , capture_title |> Http.encodeUri
-                ]
-        , body =
-            Http.emptyBody
-        , expect =
-            Http.expectJson decodeBook
-        , timeout =
-            Nothing
-        , withCredentials =
-            False
-        }
+getBooksByTitle : String -> (Result Http.Error  (Book)  -> msg) -> Cmd msg
+getBooksByTitle capture_title toMsg =
+    let
+        params =
+            List.filterMap identity
+            (List.concat
+                [])
+    in
+        Http.request
+            { method =
+                "GET"
+            , headers =
+                []
+            , url =
+                Url.Builder.crossOrigin ""
+                    [ "books"
+                    , capture_title
+                    ]
+                    params
+            , body =
+                Http.emptyBody
+            , expect =
+                Http.expectJson toMsg jsonDecBook
+            , timeout =
+                Nothing
+            , tracker =
+                Nothing
+            }
diff --git a/test/elm-sources/getBooksSource.elm b/test/elm-sources/getBooksSource.elm
--- a/test/elm-sources/getBooksSource.elm
+++ b/test/elm-sources/getBooksSource.elm
@@ -2,30 +2,39 @@
 
 import Http
 import Json.Decode exposing (..)
+import Url.Builder
+import Json.Decode as J
 
+type alias Book = {}
 
-getBooks : Bool -> Maybe (String) -> Maybe (Int) -> String -> List (Maybe (Bool)) -> Http.Request (List (Book))
-getBooks query_published query_sort query_year query_category query_filters =
+maybeBoolToIntStr : Maybe Bool -> String
+maybeBoolToIntStr mx =
+  case mx of
+    Nothing -> ""
+    Just True -> "1"
+    Just False -> "0"
+
+jsonDecBook = J.succeed {}
+
+getBooks : Bool -> (Maybe String) -> (Maybe Int) -> String -> (List (Maybe Bool)) -> (Result Http.Error  ((List Book))  -> msg) -> Cmd msg
+getBooks query_published query_sort query_year query_category query_filters toMsg =
     let
         params =
-            List.filter (not << String.isEmpty)
-                [ if query_published then
-                    "query_published="
+            List.filterMap identity
+            (List.concat
+                [ [ if query_published then
+                    Just (Url.Builder.string "published" "")
                   else
-                    ""
-                , query_sort
-                    |> Maybe.map (Http.encodeUri >> (++) "sort=")
-                    |> Maybe.withDefault ""
-                , query_year
-                    |> Maybe.map (toString >> Http.encodeUri >> (++) "year=")
-                    |> Maybe.withDefault ""
-                , Just query_category
-                    |> Maybe.map (Http.encodeUri >> (++) "category=")
-                    |> Maybe.withDefault ""
+                    Nothing ]
+                , [ query_sort
+                    |> Maybe.map (Url.Builder.string "query_sort") ]
+                , [ query_year
+                    |> Maybe.map (String.fromInt >> Url.Builder.string "query_year") ]
+                , [ Just query_category
+                    |> Maybe.map (Url.Builder.string "query_category") ]
                 , query_filters
-                    |> List.map (\val -> "query_filters[]=" ++ (val |> toString |> Http.encodeUri))
-                    |> String.join "&"
-                ]
+                    |> List.map (\val -> Just (Url.Builder.string "filters[]" (maybeBoolToIntStr val)))
+                ])
     in
         Http.request
             { method =
@@ -33,20 +42,16 @@
             , headers =
                 []
             , url =
-                String.join "/"
-                    [ ""
-                    , "books"
+                Url.Builder.crossOrigin ""
+                    [ "books"
                     ]
-                ++ if List.isEmpty params then
-                       ""
-                   else
-                       "?" ++ String.join "&" params
+                    params
             , body =
                 Http.emptyBody
             , expect =
-                Http.expectJson (list decodeBook)
+                Http.expectJson toMsg (Json.Decode.list (jsonDecBook))
             , timeout =
                 Nothing
-            , withCredentials =
-                False
+            , tracker =
+                Nothing
             }
diff --git a/test/elm-sources/getNothingSource.elm b/test/elm-sources/getNothingSource.elm
--- a/test/elm-sources/getNothingSource.elm
+++ b/test/elm-sources/getNothingSource.elm
@@ -1,32 +1,36 @@
 module GetNothingSource exposing (..)
 
 import Http
+import Url.Builder
 
 
-getNothing : Http.Request (NoContent)
-getNothing =
-    Http.request
-        { method =
-            "GET"
-        , headers =
-            []
-        , url =
-            String.join "/"
-                [ ""
-                , "nothing"
-                ]
-        , body =
-            Http.emptyBody
-        , expect =
-            Http.expectStringResponse
-                (\{ body } ->
-                    if String.isEmpty body then
-                        Ok NoContent
-                    else
-                        Err "Expected the response body to be empty"
-                )
-        , timeout =
-            Nothing
-        , withCredentials =
-            False
-        }
+getNothing : (Result Http.Error  (())  -> msg) -> Cmd msg
+getNothing toMsg =
+    let
+        params =
+            List.filterMap identity
+            (List.concat
+                [])
+    in
+        Http.request
+            { method =
+                "GET"
+            , headers =
+                []
+            , url =
+                Url.Builder.crossOrigin ""
+                    [ "nothing"
+                    ]
+                    params
+            , body =
+                Http.emptyBody
+            , expect =
+                Http.expectString 
+                     (\x -> case x of
+                     Err e -> toMsg (Err e)
+                     Ok _ -> toMsg (Ok ()))
+            , timeout =
+                Nothing
+            , tracker =
+                Nothing
+            }
diff --git a/test/elm-sources/getOneSource.elm b/test/elm-sources/getOneSource.elm
--- a/test/elm-sources/getOneSource.elm
+++ b/test/elm-sources/getOneSource.elm
@@ -2,26 +2,33 @@
 
 import Http
 import Json.Decode exposing (..)
+import Url.Builder
 
 
-getOne : Http.Request (Int)
-getOne =
-    Http.request
-        { method =
-            "GET"
-        , headers =
-            []
-        , url =
-            String.join "/"
-                [ ""
-                , "one"
-                ]
-        , body =
-            Http.emptyBody
-        , expect =
-            Http.expectJson int
-        , timeout =
-            Nothing
-        , withCredentials =
-            False
-        }
+getOne : (Result Http.Error  (Int)  -> msg) -> Cmd msg
+getOne toMsg =
+    let
+        params =
+            List.filterMap identity
+            (List.concat
+                [])
+    in
+        Http.request
+            { method =
+                "GET"
+            , headers =
+                []
+            , url =
+                Url.Builder.crossOrigin ""
+                    [ "one"
+                    ]
+                    params
+            , body =
+                Http.emptyBody
+            , expect =
+                Http.expectJson toMsg Json.Decode.int
+            , timeout =
+                Nothing
+            , tracker =
+                Nothing
+            }
diff --git a/test/elm-sources/getOneWithDynamicUrlSource.elm b/test/elm-sources/getOneWithDynamicUrlSource.elm
--- a/test/elm-sources/getOneWithDynamicUrlSource.elm
+++ b/test/elm-sources/getOneWithDynamicUrlSource.elm
@@ -1,27 +1,34 @@
 module GetOneWithDynamicUrlSource exposing (..)
 
 import Http
+import Url.Builder
 import Json.Decode exposing (..)
 
 
-getOne : String -> Http.Request (Int)
-getOne urlBase =
-    Http.request
-        { method =
-            "GET"
-        , headers =
-            []
-        , url =
-            String.join "/"
-                [ urlBase
-                , "one"
-                ]
-        , body =
-            Http.emptyBody
-        , expect =
-            Http.expectJson int
-        , timeout =
-            Nothing
-        , withCredentials =
-            False
-        }
+getOne : String -> (Result Http.Error  (Int)  -> msg) -> Cmd msg
+getOne urlBase toMsg =
+    let
+        params =
+            List.filterMap identity
+            (List.concat
+                [])
+    in
+        Http.request
+            { method =
+                "GET"
+            , headers =
+                []
+            , url =
+                Url.Builder.absolute
+                    [ "one"
+                    ]
+                    params
+            , body =
+                Http.emptyBody
+            , expect =
+                Http.expectJson toMsg Json.Decode.int
+            , timeout =
+                Nothing
+            , tracker =
+                Nothing
+            }
diff --git a/test/elm-sources/getWithaheaderSource.elm b/test/elm-sources/getWithaheaderSource.elm
--- a/test/elm-sources/getWithaheaderSource.elm
+++ b/test/elm-sources/getWithaheaderSource.elm
@@ -1,32 +1,39 @@
 module GetWithAHeaderSource exposing (..)
 
 import Http
+import Url.Builder
 import Json.Decode exposing (..)
 
 
-getWithaheader : Maybe (String) -> Maybe (Int) -> String -> Int -> Http.Request (String)
-getWithaheader header_myStringHeader header_MyIntHeader header_MyRequiredStringHeader header_MyRequiredIntHeader =
-    Http.request
-        { method =
-            "GET"
-        , headers =
+getWithaheader : (Maybe String) -> (Maybe Int) -> String -> Int -> (Result Http.Error  (String)  -> msg) -> Cmd msg
+getWithaheader header_myStringHeader header_MyIntHeader header_MyRequiredStringHeader header_MyRequiredIntHeader toMsg =
+    let
+        params =
             List.filterMap identity
-                [ Maybe.map (Http.header "myStringHeader") header_myStringHeader
-                , Maybe.map (Http.header "MyIntHeader" << toString) header_MyIntHeader
-                , Maybe.map (Http.header "MyRequiredStringHeader") (Just header_MyRequiredStringHeader)
-                , Maybe.map (Http.header "MyRequiredIntHeader" << toString) (Just header_MyRequiredIntHeader)
-                ]
-        , url =
-            String.join "/"
-                [ ""
-                , "with-a-header"
-                ]
-        , body =
-            Http.emptyBody
-        , expect =
-            Http.expectJson string
-        , timeout =
-            Nothing
-        , withCredentials =
-            False
-        }
+            (List.concat
+                [])
+    in
+        Http.request
+            { method =
+                "GET"
+            , headers =
+                List.filterMap identity
+                    [ Maybe.map (Http.header "myStringHeader") header_myStringHeader
+                    , Maybe.map (Http.header "MyIntHeader" << String.fromInt) header_MyIntHeader
+                    , Maybe.map (Http.header "MyRequiredStringHeader") (Just header_MyRequiredStringHeader)
+                    , Maybe.map (Http.header "MyRequiredIntHeader" << String.fromInt) (Just header_MyRequiredIntHeader)
+                    ]
+            , url =
+                Url.Builder.crossOrigin ""
+                    [ "with-a-header"
+                    ]
+                    params
+            , body =
+                Http.emptyBody
+            , expect =
+                Http.expectJson toMsg Json.Decode.string
+            , timeout =
+                Nothing
+            , tracker =
+                Nothing
+            }
diff --git a/test/elm-sources/getWitharesponseheaderSource.elm b/test/elm-sources/getWitharesponseheaderSource.elm
--- a/test/elm-sources/getWitharesponseheaderSource.elm
+++ b/test/elm-sources/getWitharesponseheaderSource.elm
@@ -1,27 +1,34 @@
 module GetWithAResponseHeaderSource exposing (..)
 
 import Http
+import Url.Builder
 import Json.Decode exposing (..)
 
 
-getWitharesponseheader : Http.Request (String)
-getWitharesponseheader =
-    Http.request
-        { method =
-            "GET"
-        , headers =
-            []
-        , url =
-            String.join "/"
-                [ ""
-                , "with-a-response-header"
-                ]
-        , body =
-            Http.emptyBody
-        , expect =
-            Http.expectJson string
-        , timeout =
-            Nothing
-        , withCredentials =
-            False
-        }
+getWitharesponseheader : (Result Http.Error  (String)  -> msg) -> Cmd msg
+getWitharesponseheader toMsg =
+    let
+        params =
+            List.filterMap identity
+            (List.concat
+                [])
+    in
+        Http.request
+            { method =
+                "GET"
+            , headers =
+                []
+            , url =
+                Url.Builder.crossOrigin ""
+                    [ "with-a-response-header"
+                    ]
+                    params
+            , body =
+                Http.emptyBody
+            , expect =
+                Http.expectJson toMsg Json.Decode.string
+            , timeout =
+                Nothing
+            , tracker =
+                Nothing
+            }
diff --git a/test/elm-sources/postBooksSource.elm b/test/elm-sources/postBooksSource.elm
--- a/test/elm-sources/postBooksSource.elm
+++ b/test/elm-sources/postBooksSource.elm
@@ -1,32 +1,39 @@
 module PostBooksSource exposing (..)
 
 import Http
+import Url.Builder
+import Json.Encode as Enc
 
+type alias Book = {}
+jsonEncBook = \b -> Enc.object []
 
-postBooks : Book -> Http.Request (NoContent)
-postBooks body =
-    Http.request
-        { method =
-            "POST"
-        , headers =
-            []
-        , url =
-            String.join "/"
-                [ ""
-                , "books"
-                ]
-        , body =
-            Http.jsonBody (encodeBook body)
-        , expect =
-            Http.expectStringResponse
-                (\{ body } ->
-                    if String.isEmpty body then
-                        Ok NoContent
-                    else
-                        Err "Expected the response body to be empty"
-                )
-        , timeout =
-            Nothing
-        , withCredentials =
-            False
-        }
+postBooks : Book -> (Result Http.Error  (())  -> msg) -> Cmd msg
+postBooks body toMsg =
+    let
+        params =
+            List.filterMap identity
+            (List.concat
+                [])
+    in
+        Http.request
+            { method =
+                "POST"
+            , headers =
+                []
+            , url =
+                Url.Builder.crossOrigin ""
+                    [ "books"
+                    ]
+                    params
+            , body =
+                Http.jsonBody (jsonEncBook body)
+            , expect =
+                Http.expectString 
+                     (\x -> case x of
+                     Err e -> toMsg (Err e)
+                     Ok _ -> toMsg (Ok ()))
+            , timeout =
+                Nothing
+            , tracker =
+                Nothing
+            }
diff --git a/test/elm-sources/postTwoSource.elm b/test/elm-sources/postTwoSource.elm
--- a/test/elm-sources/postTwoSource.elm
+++ b/test/elm-sources/postTwoSource.elm
@@ -3,26 +3,33 @@
 import Http
 import Json.Decode exposing (..)
 import Json.Encode
+import Url.Builder
 
 
-postTwo : String -> Http.Request (Maybe (Int))
-postTwo body =
-    Http.request
-        { method =
-            "POST"
-        , headers =
-            []
-        , url =
-            String.join "/"
-                [ ""
-                , "two"
-                ]
-        , body =
-            Http.jsonBody (Json.Encode.string body)
-        , expect =
-            Http.expectJson (maybe int)
-        , timeout =
-            Nothing
-        , withCredentials =
-            False
-        }
+postTwo : String -> (Result Http.Error  ((Maybe Int))  -> msg) -> Cmd msg
+postTwo body toMsg =
+    let
+        params =
+            List.filterMap identity
+            (List.concat
+                [])
+    in
+        Http.request
+            { method =
+                "POST"
+            , headers =
+                []
+            , url =
+                Url.Builder.crossOrigin ""
+                    [ "two"
+                    ]
+                    params
+            , body =
+                Http.jsonBody (Json.Encode.string body)
+            , expect =
+                Http.expectJson toMsg (Json.Decode.maybe (Json.Decode.int))
+            , timeout =
+                Nothing
+            , tracker =
+                Nothing
+            }
diff --git a/test/elm-sources/putNothingSource.elm b/test/elm-sources/putNothingSource.elm
--- a/test/elm-sources/putNothingSource.elm
+++ b/test/elm-sources/putNothingSource.elm
@@ -1,32 +1,36 @@
 module PutNothingSource exposing (..)
 
 import Http
+import Url.Builder
 
 
-putNothing : Http.Request (())
-putNothing =
-    Http.request
-        { method =
-            "PUT"
-        , headers =
-            []
-        , url =
-            String.join "/"
-                [ ""
-                , "nothing"
-                ]
-        , body =
-            Http.emptyBody
-        , expect =
-            Http.expectStringResponse
-                (\{ body } ->
-                    if String.isEmpty body then
-                        Ok ()
-                    else
-                        Err "Expected the response body to be empty"
-                )
-        , timeout =
-            Nothing
-        , withCredentials =
-            False
-        }
+putNothing : (Result Http.Error  (())  -> msg) -> Cmd msg
+putNothing toMsg =
+    let
+        params =
+            List.filterMap identity
+            (List.concat
+                [])
+    in
+        Http.request
+            { method =
+                "PUT"
+            , headers =
+                []
+            , url =
+                Url.Builder.crossOrigin ""
+                    [ "nothing"
+                    ]
+                    params
+            , body =
+                Http.emptyBody
+            , expect =
+                Http.expectString 
+                     (\x -> case x of
+                     Err e -> toMsg (Err e)
+                     Ok _ -> toMsg (Ok ()))
+            , timeout =
+                Nothing
+            , tracker =
+                Nothing
+            }
