diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,88 @@
+servant-router
+---
+
+`servant-router` routes a URI given a Servant API and an appropriate handler.
+In web applications,
+this is used to make single page applications (SPAs) with front-end routing,
+letting you share portions of your Servant APIs between the client and server.
+
+`servant-router` does not depend on `reflex` or any GHCJS packages.
+It's intended to be a general purpose URI router on any platform.
+Combined with `reflex-dom`, `servant-reflex`, and `reflex-dom-contrib`,
+this makes for a very satisfactory front-end Haskell experience.
+
+```haskell
+{-# LANGUAGE DataKinds     #-}
+{-# LANGUAGE TypeOperators #-}
+
+module Main where
+
+import           Control.Monad.Except
+import           Data.Proxy
+import           Reflex.Dom
+import           Reflex.Dom.Contrib.Router
+import           Servant.API
+import           Servant.Router
+
+type MyApi = "books" :> Capture "id" Int :> View
+        :<|> "search" :> QueryParam "keywords" String :> View
+myApi :: Proxy MyApi
+myApi = Proxy
+
+main :: IO ()
+-- reflex-dom-contrib provides a 'routeSite' function
+-- for routing single page applications with reflex.
+-- servant-router uses the provided uri String to perform the routing.
+main = routeSite $ \uri -> do
+  let handler = books :<|> search
+      books i = do
+        -- Here, you would get and display a book.
+        -- Return a Reflex event for changing the browser location.
+        return never
+      search Nothing = do
+        -- Here, you would display a search bar.
+        return never
+      search (Just keywords) = do
+        -- Here you would display the search bar plus results.
+        return never
+  -- With the handler constructed, run the router with the uri.
+  result <- runExceptT $ runRoute uri myApi handler
+  case result of
+    -- If 'Left', there was no correct route for the uri.
+    Left _ -> do
+      el "div" $ text "No such page"
+      return never
+    -- If 'Right', the result of the route is returned.
+    Right e -> return e
+```
+
+Serving
+---
+
+When using `servant-router` on the front-end in Single Page Applications (SPAs),
+you still need to serve the application from the back-end.
+To share the routing layout between the front-end and back-end,
+the `View` endpoints need to be converted to a verb like `Get`.
+Plus, with an SPA,
+all the end-points should serve the same HTML on the back-end.
+To do this, use the `ViewTransform` type family, and `constHandler` function.
+
+```haskell
+type Views = "books" :> View
+        :<|> "search" :> QueryParam "query" String :> View
+
+-- Equivalent to:
+--
+--   type ViewsServer = "books" :> Get '[HTML] Blaze.Html
+--          :<|> "search" :> QueryParam "query" String :> Get '[HTML] Blaze.Html
+type ViewsServer = ViewTransform Views (Get '[HTML] Blaze.Html)
+
+viewsServer :: Server ViewsServer
+viewsServer = constHandler
+	    (Proxy :: Proxy ViewsServer)
+	    (Proxy :: Proxy Handler) $
+	    docTypeHtml $ do
+	      H.head $ return ()
+	      body $
+	        script ! src "app.js" $ return ()
+```
diff --git a/servant-router.cabal b/servant-router.cabal
--- a/servant-router.cabal
+++ b/servant-router.cabal
@@ -1,5 +1,5 @@
 name:                servant-router
-version:             0.7.1
+version:             0.8.0
 synopsis:            Servant router for non-server applications.
 description:         Write Servant APIs to be routed without a server.
 homepage:            https://github.com/ElvishJerricco/servant-router
@@ -10,7 +10,7 @@
 copyright:           2016 Will Fancher
 category:            Web
 build-type:          Simple
--- extra-source-files:
+extra-source-files:  README.md
 cabal-version:       >=1.10
 
 library
@@ -35,7 +35,21 @@
                      , servant-router
                      , servant
                      , mtl
-  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
+  ghc-options:         -Wall -threaded -rtsopts -with-rtsopts=-N
+  default-language:    Haskell2010
+
+test-suite server-test
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             Server.hs
+  build-depends:       base
+                     , servant-router
+                     , servant-server
+                     , servant-blaze
+                     , mtl
+                     , warp
+                     , blaze-html
+  ghc-options:         -Wall -threaded -rtsopts -with-rtsopts=-N
   default-language:    Haskell2010
 
 source-repository head
diff --git a/src/Servant/Router.hs b/src/Servant/Router.hs
--- a/src/Servant/Router.hs
+++ b/src/Servant/Router.hs
@@ -54,16 +54,31 @@
   RPath         :: KnownSymbol sym => Proxy sym -> Router m a -> Router m a
   RPage         :: m a -> Router m a
 
+-- | Transform a layout by replacing 'View' with another type
+type family ViewTransform layout view where
+  ViewTransform (a :<|> b) view = ViewTransform a view :<|> ViewTransform b view
+  ViewTransform (a :> b) view = a :> ViewTransform b view
+  ViewTransform View view = view
+
 -- | This is similar to the @HasServer@ class from @servant-server@.
 -- It is the class responsible for making API combinators routable.
 -- 'RuoteT' is used to build up the handler types.
 -- 'Router' is returned, to be interpretted by 'routeLoc'.
 class HasRouter layout where
+  -- | A route handler.
   type RouteT layout (m :: * -> *) a :: *
+  -- | Create a constant route handler that returns @a@
+  constHandler :: Monad m => Proxy layout -> Proxy m -> a -> RouteT layout m a
+  -- | Transform a route handler into a 'Router'.
   route :: Proxy layout -> Proxy m -> Proxy a -> RouteT layout m a -> Router m a
+  -- | Create a 'Router' from a constant.
+  routeConst :: Monad m => Proxy layout -> Proxy m -> a -> Router m a
+  routeConst l m a = route l m (Proxy :: Proxy a) (constHandler l m a)
 
 instance (HasRouter x, HasRouter y) => HasRouter (x :<|> y) where
   type RouteT (x :<|> y) m a = RouteT x m a :<|> RouteT y m a
+  constHandler _ m a = constHandler (Proxy :: Proxy x) m a
+                  :<|> constHandler (Proxy :: Proxy y) m a
   route
     _
     (m :: Proxy m)
@@ -72,41 +87,47 @@
     = RChoice (route (Proxy :: Proxy x) m a x) (route (Proxy :: Proxy y) m a y)
 
 instance (HasRouter sublayout, FromHttpApiData x)
-    => HasRouter (Capture sym x :> sublayout) where
+         => HasRouter (Capture sym x :> sublayout) where
   type RouteT (Capture sym x :> sublayout) m a = x -> RouteT sublayout m a
+  constHandler _ m a _ = constHandler (Proxy :: Proxy sublayout) m a
   route _ m a f = RCapture (route (Proxy :: Proxy sublayout) m a . f)
 
 instance (HasRouter sublayout, FromHttpApiData x, KnownSymbol sym)
-    => HasRouter (QueryParam sym x :> sublayout) where
+         => HasRouter (QueryParam sym x :> sublayout) where
   type RouteT (QueryParam sym x :> sublayout) m a
     = Maybe x -> RouteT sublayout m a
+  constHandler _ m a _ = constHandler (Proxy :: Proxy sublayout) m a
   route _ m a f = RQueryParam
     (Proxy :: Proxy sym)
     (route (Proxy :: Proxy sublayout) m a . f)
 
 instance (HasRouter sublayout, FromHttpApiData x, KnownSymbol sym)
-    => HasRouter (QueryParams sym x :> sublayout) where
+         => HasRouter (QueryParams sym x :> sublayout) where
   type RouteT (QueryParams sym x :> sublayout) m a = [x] -> RouteT sublayout m a
+  constHandler _ m a _ = constHandler (Proxy :: Proxy sublayout) m a
   route _ m a f = RQueryParams
     (Proxy :: Proxy sym)
     (route (Proxy :: Proxy sublayout) m a . f)
 
 instance (HasRouter sublayout, KnownSymbol sym)
-    => HasRouter (QueryFlag sym :> sublayout) where
+         => HasRouter (QueryFlag sym :> sublayout) where
   type RouteT (QueryFlag sym :> sublayout) m a = Bool -> RouteT sublayout m a
+  constHandler _ m a _ = constHandler (Proxy :: Proxy sublayout) m a
   route _ m a f = RQueryFlag
     (Proxy :: Proxy sym)
     (route (Proxy :: Proxy sublayout) m a . f)
 
 instance (HasRouter sublayout, KnownSymbol path)
-    => HasRouter (path :> sublayout) where
+         => HasRouter (path :> sublayout) where
   type RouteT (path :> sublayout) m a = RouteT sublayout m a
+  constHandler _ = constHandler (Proxy :: Proxy sublayout)
   route _ m a page = RPath
     (Proxy :: Proxy path)
     (route (Proxy :: Proxy sublayout) m a page)
 
 instance HasRouter View where
   type RouteT View m a = m a
+  constHandler _ _ = return
   route _ _ _ = RPage
 
 -- | Use a handler to route a location, represented as a 'String'.
diff --git a/test/Server.hs b/test/Server.hs
new file mode 100644
--- /dev/null
+++ b/test/Server.hs
@@ -0,0 +1,35 @@
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TypeOperators     #-}
+
+import           Data.Proxy
+import           Network.Wai.Handler.Warp
+import           Servant
+import           Servant.HTML.Blaze
+import           Servant.Router
+import           Text.Blaze.Html5            as H hiding (main)
+import           Text.Blaze.Html5.Attributes
+
+type Views = "books" :> View
+        :<|> "search" :> QueryParam "query" String :> View
+views :: Proxy Views
+views = Proxy
+
+type Api = "api" :> "books" :> Get '[JSON] [String]
+api :: Proxy Api
+api = Proxy
+
+type WholeServer = ViewTransform Views (Get '[HTML] Html)
+              :<|> Api
+wholeServer :: Proxy WholeServer
+wholeServer = Proxy
+
+server :: Server WholeServer
+server = viewServer :<|> apiServer where
+  apiServer = return ["Book Title!"]
+  viewServer = constHandler views (Proxy :: Proxy Handler) $ docTypeHtml $ do
+    H.head $ return ()
+    body $ script ! src "app.js" $ return ()
+
+main :: IO ()
+main = run 8080 $ serve wholeServer server
