diff --git a/Setup.hs b/Setup.hs
deleted file mode 100644
--- a/Setup.hs
+++ /dev/null
@@ -1,2 +0,0 @@
-import Distribution.Simple
-main = defaultMain
diff --git a/benchmarks/Main.hs b/benchmarks/Main.hs
deleted file mode 100644
--- a/benchmarks/Main.hs
+++ /dev/null
@@ -1,13 +0,0 @@
-module Main where
-
-import Criterion.Main
-import qualified Data.Text as T
-import TextBenchmarks (TextBenchmark (..), benchmarks)
-
--- | Function to run the benchmarks using criterion
-main :: IO ()
-main = defaultMain $ map benchUrl benchmarks
-  where
-    benchUrl (TextBenchmark name f x) = bgroup name
-      [bench "Text" $ nf (T.length . f) x
-      ]
diff --git a/src/Data/Url.hs b/src/Data/Url.hs
--- a/src/Data/Url.hs
+++ b/src/Data/Url.hs
@@ -1,82 +1,201 @@
 {-# LANGUAGE
-    OverloadedStrings
+    KindSignatures
   , MultiParamTypeClasses
-  , FlexibleInstances
-  , FlexibleContexts
-  , KindSignatures
-  , InstanceSigs
+  , FunctionalDependencies
   , TypeFamilies
-  , RankNTypes
+  , TypeSynonymInstances
+  , FlexibleInstances
+  , DeriveFunctor
   #-}
 
-module Data.Url
-    ( UrlReader (..)
-    , Url (..)
-    , module Data.Url.Types ) where
+module Data.Url where
 
-import Data.Url.Types
+import Path.Extended
 
-import Data.String
-import Data.Monoid
-import Data.Monoid.Textual (TextualMonoid)
-import Control.Applicative
-import Control.Monad
+import Data.Functor.Identity
 import Control.Monad.Trans
-import Control.Monad.Reader.Class
+import Control.Monad.Reader
 
+
 -- * Classes
 
--- | @Url@ is a relationship between an underlying string type
--- @plain@, and a deployment context @m@. We try to make the deployment style
--- coercible at the top level - if the expression has a type
--- @Url String (AbsoluteUrlT String Identity)@ or
--- @Monad m => Url T.Text (GroundedUrlT LT.Text m)@ will force
--- /all use-cases within the expression/ to coerce to that type.
-class ( TextualMonoid plain
-      , MonadReader plain m
-      ) => Url plain (m :: * -> *) where
-  queryUrl :: QueryString plain -- ^ Url type, parameterized over a string type @plain@
-           -> m plain           -- ^ Rendered Url in some context.
-  plainUrl :: plain   -- ^ raw small string
-           -> m plain -- ^ Rendered string in some context.
+class Url b (m :: * -> *) where
+  pathUrl   :: Path b t
+            -> m String
+  locUrl    :: Location b t
+            -> m String
+  symbolUrl :: ( ToLocation s b t
+               ) => s
+                 -> m String
 
+instance ( Url b m
+         , MonadTrans t
+         , Monad m
+         ) => Url b (t m) where
+  pathUrl   = lift . pathUrl
+  locUrl    = lift . locUrl
+  symbolUrl = lift . symbolUrl
 
--- | Overload deployment schemes with this - then, all that's needed is a type
--- coercion to change deployment.
-class Url plain m => UrlReader plain m where
-  type Result m :: * -> *
-  runUrlReader :: Url plain m =>
-                  m b -- ^ MonadReader with index @string@ and result @b@
-               -> plain -- ^ Reader index
-               -> Result m b -- ^ Final result
 
+-- | Make an instance for your own stringless route type to use your symbols
+-- instead of strings or @Path@.
+class ToLocation a b t | a -> b t where
+  toLocation :: a -> Location b t
 
-instance ( Monad m
-         , TextualMonoid plain ) => Url plain (RelativeUrlT plain m) where
-  queryUrl = RelativeUrlT . const . return . expandRelative
-  plainUrl x = RelativeUrlT $ const $ return $ expandRelative $ QueryString x [] Nothing
+-- | Overload extraction for deployment transformers.
+class UrlReader m where
+  type RunUrlReader m :: * -> *
+  runUrlReader :: m a -- ^ MonadReader with index @string@ and result @b@
+               -> UrlAuthority -- ^ URI Scheme, hostname, and other details
+               -> RunUrlReader m a -- ^ Final result
 
+
+-- * Types
+
+-- | The hostname of a URL.
+data UrlAuthority = UrlAuthority
+  { urlScheme  :: String
+  , urlSlashes :: Bool
+  , urlAuth    :: Maybe UrlAuthent
+  , urlHost    :: String
+  , urlPort    :: Maybe Int
+  } deriving (Eq, Ord)
+
+instance Show UrlAuthority where
+  show (UrlAuthority sh sl ma h mp) =
+      sh ++ ":"
+   ++ if sl then "//" else ""
+   ++ maybe "" (\a -> show a ++ "@") ma
+   ++ h
+   ++ maybe "" (\p -> ":" ++ show p) mp
+
+data UrlAuthent = UrlAuthent
+  { urlAuthUser :: String
+  , urlAuthPass :: Maybe String
+  } deriving (Eq, Ord)
+
+instance Show UrlAuthent where
+  show (UrlAuthent u mp) = u ++ maybe "" (\p -> ":" ++ p) mp
+
+
+-- ** Relative Urls
+
+newtype RelativeUrlT m a = RelativeUrlT
+  { runRelativeUrlT :: UrlAuthority -> m a
+  } deriving Functor
+
+type RelativeUrl = RelativeUrlT Identity
+
+instance Applicative m => Applicative (RelativeUrlT m) where
+  pure x = RelativeUrlT $ const (pure x)
+  f <*> x = RelativeUrlT $ \r ->
+    (runRelativeUrlT f r) <*> (runRelativeUrlT x r)
+
+instance Monad m => Monad (RelativeUrlT m) where
+  return x = RelativeUrlT $ const (return x)
+  m >>= f = RelativeUrlT $ \r ->
+    runRelativeUrlT m r >>= (\x -> runRelativeUrlT (f x) r)
+
+instance MonadTrans RelativeUrlT where
+  lift = RelativeUrlT . const
+
+-- | Returns the base that urls are appended to - @mempty@
 instance ( Monad m
-         , TextualMonoid plain ) => UrlReader plain (RelativeUrlT plain m) where
-  type Result (RelativeUrlT plain m) = m
+         ) => MonadReader String (RelativeUrlT m) where
+  ask = return ""
+  local _ x = x
+
+instance MonadIO m => MonadIO (RelativeUrlT m) where
+  liftIO = lift . liftIO
+
+instance ( Applicative m
+         ) => Url Rel (RelativeUrlT m) where
+  pathUrl x   = pure (toFilePath x)
+  locUrl x    = pure (show x)
+  symbolUrl x = pure (show (toLocation x))
+
+instance UrlReader (RelativeUrlT m) where
+  type RunUrlReader (RelativeUrlT m) = m
   runUrlReader = runRelativeUrlT
 
-instance ( Monad m
-         , TextualMonoid plain ) => Url plain (GroundedUrlT plain m) where
-  queryUrl = GroundedUrlT . const . return . expandGrounded
-  plainUrl x = GroundedUrlT $ const $ return $ expandGrounded $ QueryString x [] Nothing
 
+-- ** Grounded Urls
+
+newtype GroundedUrlT m a = GroundedUrlT
+  { runGroundedUrlT :: UrlAuthority -> m a
+  } deriving Functor
+
+type GroundedUrl = GroundedUrlT Identity
+
+instance Applicative m => Applicative (GroundedUrlT m) where
+  pure x = GroundedUrlT $ const (pure x)
+  f <*> x = GroundedUrlT $ \r ->
+    (runGroundedUrlT f r) <*> (runGroundedUrlT x r)
+
+instance Monad m => Monad (GroundedUrlT m) where
+  return x = GroundedUrlT $ const (return x)
+  m >>= f = GroundedUrlT $ \r ->
+    runGroundedUrlT m r >>= (\x -> runGroundedUrlT (f x) r)
+
+instance MonadTrans GroundedUrlT where
+  lift = GroundedUrlT . const
+
+-- | Returns the base that urls are appended to - @/@
 instance ( Monad m
-         , TextualMonoid plain ) => UrlReader plain (GroundedUrlT plain m) where
-  type Result (GroundedUrlT plain m) = m
+         ) => MonadReader String (GroundedUrlT m) where
+  ask = return "/"
+  local _ x = x
+
+instance MonadIO m => MonadIO (GroundedUrlT m) where
+  liftIO = lift . liftIO
+
+instance ( Applicative m
+         ) => Url Abs (GroundedUrlT m) where
+  pathUrl x   = pure (toFilePath x)
+  locUrl x    = pure (show x)
+  symbolUrl x = pure (show (toLocation x))
+
+instance UrlReader (GroundedUrlT m) where
+  type RunUrlReader (GroundedUrlT m) = m
   runUrlReader = runGroundedUrlT
 
-instance ( Monad m
-         , TextualMonoid plain ) => Url plain (AbsoluteUrlT plain m) where
-  queryUrl = expandAbsolute
-  plainUrl x = expandAbsolute $ QueryString x [] Nothing
 
+-- ** Absolute Urls
+
+newtype AbsoluteUrlT m a = AbsoluteUrlT
+  { runAbsoluteUrlT :: UrlAuthority -> m a
+  } deriving Functor
+
+type AbsoluteUrl = AbsoluteUrlT Identity
+
+instance Applicative m => Applicative (AbsoluteUrlT m) where
+  pure x = AbsoluteUrlT $ const (pure x)
+  f <*> x = AbsoluteUrlT $ \r ->
+    (runAbsoluteUrlT f r) <*> (runAbsoluteUrlT x r)
+
+instance Monad m => Monad (AbsoluteUrlT m) where
+  return x = AbsoluteUrlT $ const (return x)
+  m >>= f = AbsoluteUrlT $ \r ->
+    runAbsoluteUrlT m r >>= (\x -> runAbsoluteUrlT (f x) r)
+
+instance MonadTrans AbsoluteUrlT where
+  lift = AbsoluteUrlT . const
+
+-- | Returns the base that urls are appended to - the host
 instance ( Monad m
-         , TextualMonoid plain ) => UrlReader plain (AbsoluteUrlT plain m) where
-  type Result (AbsoluteUrlT plain m) = m
+         ) => MonadReader UrlAuthority (AbsoluteUrlT m) where
+  ask = AbsoluteUrlT return
+  local f (AbsoluteUrlT g) = AbsoluteUrlT (g . f)
+
+instance MonadIO m => MonadIO (AbsoluteUrlT m) where
+  liftIO = lift . liftIO
+
+instance ( Applicative m
+         ) => Url Abs (AbsoluteUrlT m) where
+  pathUrl x   = AbsoluteUrlT (\h -> pure $ show h ++ toFilePath x)
+  locUrl x    = AbsoluteUrlT (\h -> pure $ show h ++ show x)
+  symbolUrl x = AbsoluteUrlT (\h -> pure $ show h ++ show (toLocation x))
+
+instance UrlReader (AbsoluteUrlT m) where
+  type RunUrlReader (AbsoluteUrlT m) = m
   runUrlReader = runAbsoluteUrlT
diff --git a/src/Data/Url/Types.hs b/src/Data/Url/Types.hs
deleted file mode 100644
--- a/src/Data/Url/Types.hs
+++ /dev/null
@@ -1,203 +0,0 @@
-{-# LANGUAGE
-    GADTs
-  , BangPatterns
-  , OverloadedStrings
-  , FlexibleContexts
-  , FlexibleInstances
-  , MultiParamTypeClasses
-  , DeriveFunctor
-  #-}
-
-module Data.Url.Types where
-
-import Data.String
-import Data.List
-import Data.Monoid
-import Data.Monoid.Textual (TextualMonoid)
-import Data.Functor.Identity
-import Control.Applicative
-import Control.Monad
-import Control.Monad.Trans
-import Control.Monad.Reader.Class
-
--- | Abstract data type for a Url - a "target" and GET parameters. We require @IsString@
--- and @Monoid@ for generic construction, but rendering will require a monomorphic type.
---
--- The type constructor is parameterized over it's underlying @IsString@ &
--- @Monoid@ instance.
-data QueryString a where
-  QueryString :: ( TextualMonoid a ) =>
-                 a -- location
-              -> [(a, a)] -- query parameters
-              -> Maybe a -- hash
-              -> QueryString a
-
--- | We can't provide a @Show@ instance for @QueryString@ because that would force
--- us to use @String@.
-showUrlString :: QueryString a
-              -> a
-showUrlString (QueryString !t [] !mh) =
-  maybe t (\h -> t <> "#" <> h) mh
-showUrlString (QueryString !t ((!k,!v):xs) !mh) =
-  let b = t <> "?" <> k <> "=" <> v <>
-            foldl (\acc (x,y) -> acc <> "&" <> x <> "=" <> y) "" xs
-  in
-  maybe b (\h -> b <> "#" <> h) mh
-
-
--- | Makes a @QueryString@ out of a raw target path and a GET parameter pair.
-(<?>) :: ( TextualMonoid a ) =>
-         a      -- ^ Target string
-      -> (a, a) -- ^ GET Parameter
-      -> QueryString a
-(<?>) !t !kv = QueryString t [kv] Nothing
-
-infixl 9 <?>
-
--- | Adds another GET parameter pair to a @QueryString@.
-(<&>) :: ( TextualMonoid a ) =>
-         QueryString a -- ^ Old Url
-      -> (a, a)      -- ^ Additional GET Parameter
-      -> QueryString a
-(<&>) (QueryString !t !p _) !kv = QueryString t (p ++ [kv]) Nothing
-
-infixl 8 <&>
-
-class Hashable l r where
-  -- | Adds a hash parameter to a @QueryString@.
-  (<#>) :: l -> r -> QueryString r
-
-instance ( TextualMonoid a ) => Hashable a a where
-  (<#>) t h = QueryString t [] $ Just h
-
-instance ( TextualMonoid a ) => Hashable (QueryString a) a where
-  (<#>) (QueryString !t !p _) !h = QueryString t p $ Just h
-
-infixl 7 <#>
-
-fromRoute :: ( TextualMonoid a ) =>
-             ([a], [(a, a)])
-          -> QueryString a
-fromRoute (l,qs) = QueryString (intercalate' "/" l) qs Nothing
-  where
-    intercalate' c [s] = s
-    intercalate' c (s:ss) = s <> c <> intercalate' c ss
-
-
--- | Render the Url String flatly - without anything prepended to the target.
-expandRelative :: ( TextualMonoid plain ) =>
-                  QueryString plain
-               -> plain
-expandRelative = showUrlString
-
--- | Render the Url String as grounded - prepended with a "root" @//@ character.
-expandGrounded :: ( TextualMonoid plain ) =>
-                  QueryString plain
-               -> plain
-expandGrounded !x = "/" <> showUrlString x
-
--- | Render the Url String as absolute - getting the root from a @MonadReader@
--- context.
-expandAbsolute :: ( MonadReader plain m
-                  , TextualMonoid plain ) =>
-                  QueryString plain
-               -> m plain
-expandAbsolute !x = do
-  host <- ask
-  return $ host <> "/" <> showUrlString x
-
--- | Render the Url String as absolute, but with your own configuration type.
---
--- > data SiteConfig = SiteConfig { host :: T.Text
--- >                              , cdnHost :: T.Text
--- >                              }
--- >   deriving (Show, Eq)
--- >
--- > foo :: HtmlT (Reader SiteConfig) ()
--- > foo = do
--- >   url <- lift $ expandAbsoluteWith ("foo.php" <?> ("bar","baz")) host
--- >   script_ [src_ url] ""
--- >
--- > bar :: LT.Text
--- > bar = (runReader (runTextT foo)) $
--- >   SiteConfig "example.com" "cdn.example.com"
-expandAbsoluteWith :: ( MonadReader a m
-                      , TextualMonoid plain ) =>
-                      QueryString plain
-                   -> (a -> plain)
-                   -> m plain
-expandAbsoluteWith !x f = do
-  root <- liftM f ask
-  return $ root <> "/" <> showUrlString x
-
-newtype RelativeUrlT h m b = RelativeUrlT { runRelativeUrlT :: h -> m b }
-  deriving Functor
-
-instance Applicative f => Applicative (RelativeUrlT h f) where
-  (<*>) f x = RelativeUrlT $ \a ->
-    (<*>) (runRelativeUrlT f a) (runRelativeUrlT x a)
-
-instance Monad m => Monad (RelativeUrlT h m) where
-  return x = RelativeUrlT $ \_ -> return x
-  m >>= f = RelativeUrlT $ \a ->
-    runRelativeUrlT m a >>= (\x -> runRelativeUrlT (f x) a)
-
-instance MonadTrans (RelativeUrlT h) where
-  lift = RelativeUrlT . const
-
-instance ( Monad m
-         , IsString h ) => MonadReader h (RelativeUrlT h m) where
-  ask = return ""
-
-instance MonadIO m => MonadIO (RelativeUrlT h m) where
-  liftIO = lift . liftIO
-
-type RelativeUrl h b = RelativeUrlT h Identity b
-
-newtype GroundedUrlT h m b = GroundedUrlT { runGroundedUrlT :: h -> m b }
-  deriving Functor
-
-instance Applicative f => Applicative (GroundedUrlT h f) where
-  (<*>) f x = GroundedUrlT $ \a ->
-    (<*>) (runGroundedUrlT f a) (runGroundedUrlT x a)
-
-instance Monad m => Monad (GroundedUrlT h m) where
-  return x = GroundedUrlT $ \_ -> return x
-  m >>= f = GroundedUrlT $ \a ->
-    runGroundedUrlT m a >>= (\x -> runGroundedUrlT (f x) a)
-
-instance MonadTrans (GroundedUrlT h) where
-  lift = GroundedUrlT . const
-
-instance ( Monad m
-         , IsString h ) => MonadReader h (GroundedUrlT h m) where
-  ask = return "/"
-
-instance MonadIO m => MonadIO (GroundedUrlT h m) where
-  liftIO = lift . liftIO
-
-type GroundedUrl h b = GroundedUrlT h Identity b
-
-newtype AbsoluteUrlT h m b = AbsoluteUrlT { runAbsoluteUrlT :: h -> m b }
-  deriving Functor
-
-instance Applicative f => Applicative (AbsoluteUrlT h f) where
-  (<*>) f x = AbsoluteUrlT $ \a ->
-    (<*>) (runAbsoluteUrlT f a) (runAbsoluteUrlT x a)
-
-instance Monad m => Monad (AbsoluteUrlT h m) where
-  return x = AbsoluteUrlT $ const $ return x
-  m >>= f = AbsoluteUrlT $ \a ->
-    runAbsoluteUrlT m a >>= (\x -> runAbsoluteUrlT (f x) a)
-
-instance MonadTrans (AbsoluteUrlT h) where
-  lift = AbsoluteUrlT . const
-
-instance ( Monad m
-         , IsString h ) => MonadReader h (AbsoluteUrlT h m) where
-  ask = AbsoluteUrlT return
-
-instance MonadIO m => MonadIO (AbsoluteUrlT h m) where
-  liftIO = lift . liftIO
-
-type AbsoluteUrl h b = AbsoluteUrlT h Identity b
diff --git a/test/Spec.hs b/test/Spec.hs
deleted file mode 100644
--- a/test/Spec.hs
+++ /dev/null
@@ -1,1 +0,0 @@
-{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
diff --git a/urlpath.cabal b/urlpath.cabal
--- a/urlpath.cabal
+++ b/urlpath.cabal
@@ -1,75 +1,12 @@
 Name:                   urlpath
-Version:                2.1.0
+Version:                3.0.0
 Author:                 Athan Clark <athan.clark@gmail.com>
 Maintainer:             Athan Clark <athan.clark@gmail.com>
 License:                MIT
 License-File:           LICENSE
 Category:               Web, Data
-Synopsis:               Painfully simple URL writing combinators
-Description:
-  Simple URL DSL for Haskell.
-  .
-  This library tries to make it easier for people to write Url strings,
-  structurally. Packages like <https://hackage.haskell.org/package/yesod-routes Yesod Routes>
-  do a wonderful job at implementing string-free routing and
-  references, but sometimes we have to compromise. This tries to make that
-  compromise less painful.
-  .
-  Use bare combinators to render your strings (kinda useless):
-  .
-  >  expandRelative $ "foo.php" <?> ("key1","bar") <&> ("key2","baz")
-  >
-  >  ↪ "foo.php?key1=bar&key2=baz"
-  .
-  ... or use the MonadReader instance for a configurable host:
-  .
-  >  let path = runAbsoluteUrl $ url $ "foo.php" <?> ("key1","bar") <&> ("key2","baz")
-  >  path "example.com"
-  >
-  >  ↪ "example.com/foo.php?key1=bar&key2=baz"
-  .
-  @url@ puts the @UrlString@ in a MonadReader that we can use for applying our
-  host. We use different monads for different deployment schemes (currently we
-  have 3 - @RelativeUrl@, @GroundedUrl@, and @AbsoluteUrl@), which we can
-  integrate in different libraries, like Lucid:
-  .
-  >  (runAbsoluteUrl $ renderTextT $ do
-  >      foo <- lift $ url $ "foo" <?> ("bar","baz")
-  >      script_ [src_ foo] "" )
-  >  ) "example.com"
-  >
-  >  ↪ "<script src=\"example.com/foo?bar=baz\"></script>"
-  .
-  ... and in Scotty ...
-  .
-  >  main :: IO ()
-  >  main = scottyT 3000
-  >      rootConf
-  >      rootConf
-  >      run
-  >
-  >    where
-  >      rootConf = flip runAbsoluteT "http://example.com"
-  >
-  >      run :: ( MonadIO m
-  >             , MonadReader T.Text m
-  >             , Url T.Text m ) =>
-  >             ScottyT LT.Text m ()
-  >      run = get "/" $ do
-  >        path <- lift $ url $ "foo" <?> ("bar","baz")
-  >        text $ LT.fromStrict path
-  >
-  >  λ> curl localhost:3000/
-  >  ↪ "http://example.com/foo?bar=baz"
-  .
-  Note that in the scotty example, we don't use one of our deployment schemes -
-  this is because the @scottyT@ function expects it's underlying monad to be an
-  instance of @MonadIO@, which we can only instantiate in our monad transformers.
-  .
-  Please take mind - the string type underlying the Url rendering is generalized
-  to @Data.String.IsString@ for convenient use with @-XOverloadedStrings@. However,
-  due to that generality, we need to specify the monomorphic type (like
-  @Data.Text.Text@ above).
+Synopsis:               Painfully simple URL deployment.
+-- Description:
 
 Cabal-Version:          >= 1.10
 Build-Type:             Simple
@@ -79,38 +16,9 @@
   HS-Source-Dirs:       src
   GHC-Options:          -Wall
   Exposed-Modules:      Data.Url
-                        Data.Url.Types
-  Build-Depends:        base >= 4 && < 5
-                      , mtl
-                      , transformers
-                      , monoid-subclasses
-
-Test-Suite spec
-  Type:                 exitcode-stdio-1.0
-  Default-Language:     Haskell2010
-  Hs-Source-Dirs:       src
-                      , test
-  Ghc-Options:          -Wall
-  Main-Is:              Spec.hs
-  Build-Depends:        base
-                      , hspec
-                      , QuickCheck
-                      , quickcheck-instances
+  Build-Depends:        base >= 4.8 && < 5
                       , mtl
-                      , text
-                      , transformers
-                      , monoid-subclasses
-
-benchmark bench
-  type:                 exitcode-stdio-1.0
-  hs-source-dirs:       benchmarks
-  main-is:              Main.hs
-  build-depends:        base
-                      , deepseq
-                      , criterion
-                      , text
-                      , urlpath >= 0.2
-  ghc-options:          -O2
+                      , path-extra
 
 Source-Repository head
   Type:                 git
