diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,30 +1,8 @@
-Copyright Andrew Martin (c) 2017
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
+Copyright 2017-2019 Andrew Martin
+Copyright 2017-2019 Kyle McKean
 
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 
-    * Neither the name of Andrew Martin nor the names of other
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/src/Trasa/Core.hs b/src/Trasa/Core.hs
--- a/src/Trasa/Core.hs
+++ b/src/Trasa/Core.hs
@@ -149,8 +149,8 @@
 import qualified Data.HashMap.Strict as HM
 import qualified Data.Semigroup as SG
 import Data.HashMap.Strict (HashMap)
-import Data.Vinyl (Rec(..),rmap,rtraverse)
-import Data.Vinyl.TypeLevel (type (++))
+import qualified Topaz.Rec as Topaz
+import Topaz.Types (Rec(..), type (++))
 
 import Trasa.Method
 import Trasa.Url
@@ -173,6 +173,7 @@
 mapMany :: (forall x. f x -> g x) -> Many f a -> Many g a
 mapMany eta (Many m) = Many (fmap eta m)
 
+-- | the type of the HTTP message body (json, text, etc) <https://en.wikipedia.org/wiki/HTTP_message_body>
 data Bodiedness = forall a. Body a | Bodyless
 
 data RequestBody :: (Type -> Type) -> Bodiedness -> Type where
@@ -202,8 +203,9 @@
   PathConsCapture :: !(cap a) -> !(Path cap as) -> Path cap (a ': as)
   PathConsMatch :: !T.Text -> !(Path cap as) -> Path cap as
 
+-- | flipped ($), useful for constructing routes. e.g.
+-- >  match "add" ./ capture int ./ capture int ./ end
 infixr 7 ./
-
 (./) :: (a -> b) -> a -> b
 (./) f a = f a
 
@@ -251,15 +253,15 @@
 list = QueryList
 
 qend :: Rec (Query qpf) '[]
-qend = RNil
+qend = RecNil
 
 infixr 7 .&
 
 (.&) :: Query qpf q -> Rec (Query qpf) qs -> Rec (Query qpf) (q ': qs)
-(.&) = (:&)
+(.&) = RecCons
 
 mapQuery :: (forall x. f x -> g x) -> Rec (Query f) qs -> Rec (Query g) qs
-mapQuery eta = rmap $ \case
+mapQuery eta = Topaz.map $ \case
   QueryFlag key -> QueryFlag key
   QueryOptional key query -> QueryOptional key (eta query)
   QueryList key query -> QueryList key (eta query)
@@ -457,22 +459,22 @@
       .  Path CaptureEncoding caps
       -> Rec Identity caps
       -> [T.Text]
-    encodePath PathNil RNil = []
+    encodePath PathNil RecNil = []
     encodePath (PathConsMatch str ps) xs = str : encodePath ps xs
-    encodePath (PathConsCapture (CaptureEncoding enc) ps) (Identity x :& xs) = enc x : encodePath ps xs
+    encodePath (PathConsCapture (CaptureEncoding enc) ps) (Identity x `RecCons` xs) = enc x : encodePath ps xs
     encodeQueries
       :: forall qrys
       .  Rec (Query CaptureEncoding) qrys
       -> Rec Parameter qrys
       -> HM.HashMap T.Text QueryParam
-    encodeQueries RNil RNil = HM.empty
-    encodeQueries (QueryFlag key :& encs) (ParameterFlag on :& qs) =
+    encodeQueries RecNil RecNil = HM.empty
+    encodeQueries (QueryFlag key `RecCons` encs) (ParameterFlag on `RecCons` qs) =
       if on then HM.insert key QueryParamFlag rest else rest
       where rest = encodeQueries encs qs
-    encodeQueries (QueryOptional key (CaptureEncoding enc) :& encs) (ParameterOptional mval :& qs) =
+    encodeQueries (QueryOptional key (CaptureEncoding enc) `RecCons` encs) (ParameterOptional mval `RecCons` qs) =
       maybe rest (\val -> HM.insert key (QueryParamSingle (enc val)) rest) mval
       where rest = encodeQueries encs qs
-    encodeQueries (QueryList key (CaptureEncoding enc) :& encs) (ParameterList vals :& qs) =
+    encodeQueries (QueryList key (CaptureEncoding enc) `RecCons` encs) (ParameterList vals `RecCons` qs) =
        HM.insert key (QueryParamList (fmap enc vals)) (encodeQueries encs qs)
 
 -- | Only useful to implement packages like 'trasa-server'
@@ -557,7 +559,7 @@
        in res1 ++ res2
 
 parseQueryWith :: Rec (Query CaptureDecoding) querys -> QueryString -> Either TrasaErr (Rec Parameter querys)
-parseQueryWith decoding (QueryString querys) = rtraverse param decoding
+parseQueryWith decoding (QueryString querys) = Topaz.traverse param decoding
   where
     param :: forall qry. Query CaptureDecoding qry -> Either TrasaErr (Parameter qry)
     param = \case
@@ -579,11 +581,11 @@
      IxedRec CaptureDecoding n xs
   -> Vec n T.Text
   -> Maybe (Rec Identity xs)
-decodeCaptureVector IxedRecNil VecNil = Just RNil
+decodeCaptureVector IxedRecNil VecNil = Just RecNil
 decodeCaptureVector (IxedRecCons (CaptureDecoding decode) rnext) (VecCons piece vnext) = do
   val <- decode piece
   vals <- decodeCaptureVector rnext vnext
-  return (Identity val :& vals)
+  return (Identity val `RecCons` vals)
 
 type family ParamBase (param :: Param) :: Type where
   ParamBase Flag = Bool
@@ -637,16 +639,16 @@
      -> Rec (Query qf) qrys
      -> RequestBody rqf request
      -> Arguments caps qrys request z
-  go k PathNil RNil RequestBodyAbsent =
-    k RNil RNil RequestBodyAbsent
-  go k PathNil RNil (RequestBodyPresent _) =
-    \reqBod -> k RNil RNil (RequestBodyPresent (Identity reqBod))
-  go k PathNil (q :& qs) b =
-    \qt -> go (\caps querys reqBody -> k caps (parameter q qt :& querys) reqBody) PathNil qs b
+  go k PathNil RecNil RequestBodyAbsent =
+    k RecNil RecNil RequestBodyAbsent
+  go k PathNil RecNil (RequestBodyPresent _) =
+    \reqBod -> k RecNil RecNil (RequestBodyPresent (Identity reqBod))
+  go k PathNil (q `RecCons` qs) b =
+    \qt -> go (\caps querys reqBody -> k caps (parameter q qt `RecCons` querys) reqBody) PathNil qs b
   go k (PathConsMatch _ pnext) qs b =
     go k pnext qs b
   go k (PathConsCapture _ pnext) qs b =
-    \c -> go (\caps querys reqBod -> k (Identity c :& caps) querys reqBod) pnext qs b
+    \c -> go (\caps querys reqBod -> k (Identity c `RecCons` caps) querys reqBod) pnext qs b
   parameter :: forall param. Query qf param -> ParamBase param -> Parameter param
   parameter (QueryFlag _) b = ParameterFlag b
   parameter (QueryOptional _ _) m = ParameterOptional m
@@ -667,10 +669,10 @@
     -> RequestBody Identity request
     -> Arguments caps qrys request x
     -> x
-  go RNil RNil RequestBodyAbsent f = f
-  go RNil RNil (RequestBodyPresent (Identity b)) f = f b
-  go RNil (q :& qs) b f = go RNil qs b (f (demoteParameter q))
-  go (Identity c :& cs) qs b f = go cs qs b (f c)
+  go RecNil RecNil RequestBodyAbsent f = f
+  go RecNil RecNil (RequestBodyPresent (Identity b)) f = f b
+  go RecNil (q `RecCons` qs) b f = go RecNil qs b (f (demoteParameter q))
+  go (Identity c `RecCons` cs) qs b f = go cs qs b (f c)
 
 -- | A route with all types hidden: the captures, the request body,
 --   and the response body. This is needed so that users can
@@ -782,8 +784,8 @@
   HideIx :: !(f n a) -> HideIx f a
 
 -- toIxedRec :: Rec f xs -> HideIx (IxedRec f) xs
--- toIxedRec RNil = HideIx IxedRecNil
--- toIxedRec (r :& rs) = case toIxedRec rs of
+-- toIxedRec RecNil = HideIx IxedRecNil
+-- toIxedRec (r `RecCons` rs) = case toIxedRec rs of
 --   HideIx x -> HideIx (IxedRecCons r x)
 
 snocVec :: a -> Vec n a -> Vec ('S n) a
diff --git a/src/Trasa/Tutorial.hs b/src/Trasa/Tutorial.hs
deleted file mode 100644
--- a/src/Trasa/Tutorial.hs
+++ /dev/null
@@ -1,88 +0,0 @@
-{-# OPTIONS_GHC -fno-warn-unused-imports #-}
-
-{-| Users of this library should a data type representing all possible
-    routes available in a web application. It is recommended that
-    this type be named @Route@, but this is not required.
--}
-
-module Trasa.Tutorial
-  ( -- * Dispatch and Routing
-    -- $dispatchandrouting
-  ) where
-
-import Trasa.Core
-import qualified Trasa.Method as M
-import Data.Vinyl (Rec)
-import Data.Kind (Type)
-import Data.Text (Text)
-
--- $setup
--- >>> :set -XDataKinds
--- >>> :set -XKindSignatures
--- >>> :set -XGADTs
--- >>> :set -XOverloadedStrings
-
--- $dispatchandrouting
--- In this example, we will write web application that maintains three
--- counters. The end user will be able to perform various operations
--- that manipulate the values of these counters and ask for their
--- current value. We begin by defining our route type:
---
--- >>> :{
--- data Counter = Red | Green | Blue
---   deriving (Show,Read)
--- data Route :: [Type] -> [Param] -> Bodiedness -> Type -> Type where
---   AssignR :: Route '[Counter,Int] '[] 'Bodyless ()
---   IncrementR :: Route '[Counter] '[] 'Bodyless Int
---   QueryR :: Route '[Counter] '[]Bodyless Int
---   TotalR :: Route '[] '[] 'Bodyless Int
--- int :: CaptureCodec Int
--- int = showReadCaptureCodec
--- counter :: CaptureCodec Counter
--- counter = showReadCaptureCodec
--- bodyUnit :: BodyCodec ()
--- bodyUnit = BodyCodec (pure "text/plain") (const "") (const (Right ()))
--- bodyInt :: BodyCodec Int
--- bodyInt = showReadBodyCodec
--- meta :: Route captures querys request response -> MetaCodec captures querys request response
--- meta x = metaBuilderToMetaCodec $ case x of
---   AssignR -> Meta
---     (match "assign" ./ capture counter ./ match "to" ./ capture int ./ end)
---     qend
---     bodyless (resp bodyUnit) M.post
---   IncrementR -> Meta
---     (match "increment" ./ capture counter ./ end)
---     qend
---     bodyless (resp bodyInt) M.post
---   QueryR -> Meta
---     (match "query" ./ capture counter ./ end)
---     qend
---     bodyless (resp bodyInt) M.get
---   TotalR -> Meta
---     (match "total" ./ end)
---     qend
---     bodyless (resp bodyInt) M.get
--- :}
---
--- Now, we can start using our routes. To do this, we take functions that
--- @trasa@ exports and partially apply them to the route metadata that
--- we have created. We can start with prepare and link:
---
--- >>> prepare = prepareWith meta
--- >>> :t prepare
--- prepare
---   :: Route captures query request response
---      -> Arguments captures query request (Prepared Route response)
--- >>> :{
--- link = linkWith (metaCodecToMetaClient . meta)
--- :}
---
--- >>> :t link
--- link :: Prepared Route response -> Url
---
--- Now we can use link to encode our routes:
---
--- >>> link (prepare AssignR Green 5)
--- "/assign/Green/to/5"
---
---
diff --git a/test/Doctest.hs b/test/Doctest.hs
new file mode 100644
--- /dev/null
+++ b/test/Doctest.hs
@@ -0,0 +1,10 @@
+module Main (main) where
+
+import Test.DocTest (doctest)
+
+main :: IO ()
+main = do
+  putStrLn "\nRUNNING DOCTESTS"
+  doctest
+    [ "src"
+    ]
diff --git a/test/Main.hs b/test/Main.hs
deleted file mode 100644
--- a/test/Main.hs
+++ /dev/null
@@ -1,201 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE InstanceSigs #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE KindSignatures #-}
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE TypeApplications #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE FlexibleContexts #-}
-
-import Text.Read (readMaybe)
-import Trasa.Core
-import Trasa.Core.Implicit
-import qualified Trasa.Method as M
-import Data.Vinyl
-import Data.Kind (Type)
-
-import qualified Data.ByteString.Lazy.Char8 as LBSC
-import qualified Data.Text as T
-
-import Test.Tasty
-import Test.Tasty.QuickCheck as QC
-import Test.Tasty.HUnit
-import Data.Functor.Identity
-import Data.Monoid
-
-import Test.DocTest (doctest)
-
-main :: IO ()
-main = do
-  putStrLn "\nRUNNING DOCTESTS"
-  doctest
-    [ "src"
-    ]
-  putStrLn "\nPRETTY ROUTER"
-  putStrLn (prettyRouter (router @Route))
-  putStrLn "\nRUNNING OTHER TESTS"
-  defaultMain tests
-
-tests :: TestTree
-tests = testGroup "Tests" [properties, unitTests]
-
--- todo: add a property test to show that parse and link
--- form a partial isomorphism.
-properties :: TestTree
-properties = testGroup "Properties"
-  [ QC.testProperty "roundtrip link parse" roundtripLinkParse
-  ]
-
-unitTests :: TestTree
-unitTests = testGroup "Unit Tests"
-  [ testCase "link addition route"
-      $ link (prepare AdditionR 12 5 (Just 3)) @?= decodeUrl "/add/12/5?more=3"
-  , testCase "link left pad route"
-      $ link (prepare LeftPadR 5 "foo") @?= decodeUrl "/pad/left/5"
-  , testCase "parse hello route"
-      $ parseUrl "/hello" @?= Right (conceal (prepare HelloR))
-  , testCase "parse addition route"
-      $ parseUrl "/add/6/3" @?= Right (conceal (prepare AdditionR 6 3 Nothing))
-  ]
-
-parseUrl :: T.Text -> Either TrasaErr (Concealed Route)
-parseUrl url = parse "GET" (decodeUrl url) Nothing
-
-data Route :: [Type] -> [Param] -> Bodiedness -> Type -> Type where
-  EmptyR :: Route '[] '[] Bodyless Int
-  HelloR :: Route '[] '[] Bodyless Int
-  AdditionR :: Route '[Int,Int] '[Optional Int] Bodyless Int
-  IdentityR :: Route '[String] '[] Bodyless String
-  LeftPadR :: Route '[Int] '[] (Body String) String
-  TrickyOneR :: Route '[Int] '[] Bodyless String
-  TrickyTwoR :: Route '[Int,Int] '[] Bodyless String
-
-instance EnumerableRoute Route where
-  enumerateRoutes =
-    [ Constructed HelloR
-    , Constructed AdditionR
-    , Constructed IdentityR
-    , Constructed LeftPadR
-    , Constructed TrickyOneR
-    , Constructed TrickyTwoR
-    , Constructed EmptyR
-    ]
-
-instance HasMeta Route where
-  type CaptureStrategy Route = CaptureCodec
-  type QueryStrategy Route = CaptureCodec
-  type RequestBodyStrategy Route = Many BodyCodec
-  type ResponseBodyStrategy Route = Many BodyCodec
-  meta :: Route ps qs rq rp -> MetaCodec ps qs rq rp
-  meta x = metaBuilderToMetaCodec $ case x of
-    EmptyR -> Meta
-      end
-      qend
-      bodyless (resp bodyInt) M.get
-    HelloR -> Meta
-      (match "hello" ./ end)
-      qend
-      bodyless (resp bodyInt) M.get
-    AdditionR -> Meta
-      (match "add" ./ capture int ./ capture int ./ end)
-      (optional "more" int .& qend)
-      bodyless (resp bodyInt) M.get
-    IdentityR -> Meta
-      (match "identity" ./ capture string ./ end)
-      qend
-      bodyless (resp bodyString) M.get
-    LeftPadR -> Meta
-      (match "pad" ./ match "left" ./ capture int ./ end)
-      qend
-      (body bodyString) (resp bodyString) M.get
-    TrickyOneR -> Meta
-      (match "tricky" ./ capture int ./ match "one" ./ end)
-      qend
-      bodyless (resp bodyString) M.get
-    TrickyTwoR -> Meta
-      (capture int ./ capture int ./ match "two" ./ end)
-      qend
-      bodyless (resp bodyString) M.get
-
-int :: CaptureCodec Int
-int = CaptureCodec (T.pack . show) (readMaybe . T.unpack)
-
-string :: CaptureCodec String
-string = CaptureCodec T.pack (Just . T.unpack)
-
-bodyString :: BodyCodec String
-bodyString = BodyCodec (pure "text/plain") LBSC.pack (Right . LBSC.unpack)
-
-bodyUnit :: BodyCodec ()
-bodyUnit = BodyCodec (pure "text/plain") (const "") (const (Right ()))
-
-note :: e -> Maybe a -> Either e a
-note e Nothing = Left e
-note _ (Just x) = Right x
-
-bodyInt :: BodyCodec Int
-bodyInt = BodyCodec (pure "text/plain") (LBSC.pack . show)
-                    (note "Could not decode int" . readMaybe . LBSC.unpack)
-
-roundtripLinkParse :: Concealed Route -> Property
-roundtripLinkParse c@(Concealed route captures querys reqBody) =
-  (case reqBody of
-    RequestBodyPresent _ -> False
-    RequestBodyAbsent -> True
-  )
-  ==>
-  Right c == parseUrl (encodeUrl (link (Prepared route captures querys reqBody)))
-
--- This instance is defined only so that the test suite can do
--- its job. It not not neccessary or recommended to write this
--- instance in production code.
-instance Eq (Concealed Route) where
-  Concealed rt1 ps1 qs1 rq1 == Concealed rt2 ps2 qs2 rq2 = case (rt1,rt2) of
-    (AdditionR,AdditionR) -> ps1 == ps2 && qs1 == qs2 && rq1 == rq2
-    (IdentityR,IdentityR) -> ps1 == ps2 && qs1 == qs2 && rq1 == rq2
-    (LeftPadR,LeftPadR) -> case (rq1,rq2) of
-      (RequestBodyPresent a, RequestBodyPresent b) -> ps1 == ps2 && qs1 == qs2 && a == b
-    (TrickyOneR,TrickyOneR) -> ps1 == ps2 && qs1 == qs2 && rq1 == rq2
-    (TrickyTwoR,TrickyTwoR) -> ps1 == ps2 && qs1 == qs2 && rq1 == rq2
-    (HelloR,HelloR) -> ps1 == ps2 && qs1 == qs2 && rq1 == rq2
-    (EmptyR,EmptyR) -> ps1 == ps2 && qs1 == qs2 && rq1 == rq2
-
-instance Arbitrary (Concealed Route) where
-  arbitrary = oneof
-    [ Concealed AdditionR <$> arbitrary <*> arbitrary <*> arbitrary
-    , Concealed IdentityR <$> arbitrary <*> arbitrary <*> arbitrary
-    , Concealed LeftPadR <$> arbitrary <*> arbitrary <*> arbitrary
-    , Concealed TrickyOneR <$> arbitrary <*> arbitrary <*> arbitrary
-    , Concealed TrickyTwoR <$> arbitrary <*> arbitrary <*> arbitrary
-    , Concealed HelloR <$> arbitrary <*> arbitrary <*> arbitrary
-    , Concealed EmptyR <$> arbitrary <*> arbitrary <*> arbitrary
-    ]
-
-instance Show (Concealed Route) where
-  show (Concealed r a q b) = show (link (Prepared r a q b))
-
-instance Eq a => Eq (Parameter (Optional a)) where
-  ParameterOptional m1 == ParameterOptional m2 = m1 == m2
-
-instance Arbitrary (Rec Identity '[]) where
-  arbitrary = pure RNil
-
-instance (Arbitrary r, Arbitrary (Rec Identity rs)) => Arbitrary (Rec Identity (r ': rs)) where
-  arbitrary = (:&) <$> (Identity <$> arbitrary) <*> arbitrary
-
-instance Arbitrary (Rec Parameter '[]) where
-  arbitrary = pure RNil
-
-instance (Arbitrary r, Arbitrary (Rec Parameter rs)) => Arbitrary (Rec Parameter (Optional r ': rs)) where
-  arbitrary = (:&) <$> (ParameterOptional <$> arbitrary) <*> arbitrary
-
-instance Arbitrary (RequestBody f 'Bodyless) where
-  arbitrary = pure RequestBodyAbsent
-
-instance Arbitrary a => Arbitrary (RequestBody Identity (Body a)) where
-  arbitrary = RequestBodyPresent . Identity <$> arbitrary
-
-instance Eq (RequestBody f 'Bodyless) where
-  RequestBodyAbsent == RequestBodyAbsent = True
diff --git a/trasa.cabal b/trasa.cabal
--- a/trasa.cabal
+++ b/trasa.cabal
@@ -1,24 +1,40 @@
-name: trasa
-version: 0.3
-synopsis: Type Safe Web Routing
-homepage: https://github.com/haskell-trasa/trasa#readme
-license: BSD3
-license-file: LICENSE
-author: Kyle McKean
-maintainer: mckean.kylej@gmail.com
-copyright: 2017 Kyle McKean
-category: Web
-build-type: Simple
-cabal-version: >=1.10
+cabal-version: 2.2
+name:
+  trasa
+version:
+  0.4
+synopsis:
+  Type Safe Web Routing
 description:
   This library is a solution for http-based routing and dispatch. Its
   goals are similar to the goals of `servant`, however, `trasa` relies
   on very different mechanisms to accomplish those goals. All typeclasses
   in this library are optional. All of the real work is accomplished with GADTs, 
   universal quantification, and plain old haskell data types.
+homepage:
+  https://github.com/haskell-trasa/trasa
+author:
+  Andrew Martin
+  Kyle McKean
+maintainer:
+  Andrew Martin <andrew.thaddeus@gmail.com>
+  Kyle McKean <mckean.kylej@gmail.com>
+  chessai <chessai1996@gmail.com>
+license:
+  MIT
+license-file:
+  LICENSE
+copyright:
+  © 2017-2019 Andrew Martin
+  © 2017-2019 Kyle McKean
+category:
+  Web
+build-type:
+  Simple
 
 library
-  hs-source-dirs:      src
+  hs-source-dirs:
+    src
   exposed-modules:
     Trasa.Method
     Trasa.Url
@@ -26,35 +42,54 @@
     Trasa.Error
     Trasa.Core
     Trasa.Core.Implicit
-    Trasa.Tutorial
+--    Trasa.Tutorial
   build-depends:
-      base >= 4.7 && < 5
-    , bytestring == 0.10.*
+    , base >= 4.9 && < 5
     , binary == 0.8.*
-    , text == 1.2.*
-    , vinyl >= 0.5 && < 0.9
+    , bytestring == 0.10.*
     , hashable == 1.2.*
-    , http-types >= 0.9
     , http-media >= 0.6 && < 0.8
+    , http-types >= 0.9
+    , quantification == 0.5.0
+    , text == 1.2.*
     , unordered-containers >= 0.2 && < 0.3
-  default-language:    Haskell2010
+  default-language:
+    Haskell2010
 
-test-suite test
-  type: exitcode-stdio-1.0
-  hs-source-dirs: test
-  main-is: Main.hs
-  build-depends: 
-      base
-    , trasa
-    , tasty
-    , tasty-quickcheck
-    , tasty-hunit
-    , bytestring
-    , text
-    , vinyl
+test-suite doctest
+  type:
+    exitcode-stdio-1.0
+  hs-source-dirs:
+    test
+  main-is:
+    Doctest.hs
+  build-depends:
+    , base
     , doctest
-  ghc-options: -threaded -rtsopts -with-rtsopts=-N
-  default-language: Haskell2010
+  default-language:
+    Haskell2010
+
+--test-suite test
+--  type:
+--    exitcode-stdio-1.0
+--  hs-source-dirs:
+--    test
+--  main-is:
+--    Main.hs
+--  build-depends:
+--      base
+--    , trasa
+--    , tasty
+--    , tasty-quickcheck
+--    , tasty-hunit
+--    , bytestring
+--    , text
+--    , quantification
+--  ghc-options:
+--    -threaded
+--    -rtsopts -with-rtsopts=-N
+--  default-language:
+--    Haskell2010
 
 source-repository head
   type:     git
