diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,7 +1,109 @@
-# snap-web-routes: Type safe URLs for Snap
+# snap-web-routes
 
-`snap-web-routes` provides type safe URLs for Snap using [`web routes`](http://hackage.haskell.org/package/web-routes).
+## Type safe URLs for Snap
 
-# How to use
+[`Snap web routes`](http://hackage.haskell.org/package/snap-web-routes) provides type safe URLs for Snap using [`web routes`](http://hackage.haskell.org/package/web-routes).
 
-See `Snap.Web.Routes` for instructions.
+## How to use
+
+The tutorial assumes you have a standard Snap app layout with an Application.hs and Site.hs. If your setup differs you'll need to adapt the instructions accordingly.
+
+### `Application.hs`
+
+To get going, you'll need to add a few things to `Application.hs`. This includes creating the URL data type and adding the routing function to our `App` data type.
+
+    -- Enable a few extensions
+    {-# LANGUAGE FlexibleInstances #-} -- Needed by
+    {-# LANGUAGE TypeFamilies      #-} -- web-routes
+    {-# LANGUAGE DeriveGeneric     #-} -- Needed to derive Generic
+                                       -- for our URL data type
+
+    -- Paths and params use Text.
+    import Data.Text (Text)
+
+    -- Snap.Web.Routes.Types exports everything you need to
+    -- define your PathInfo and MonadRoute instances.
+    import Snap.Web.Routes.Types
+
+    -- Your URL data type.  Deriving a `Generic` instance gives
+    -- you a `PathInfo` instance for free.
+    data AppUrl
+        = Count Int
+        | Echo Text
+        | Paths [Text]
+          deriving (Generic)
+
+    -- Extend your App type to include a routing function.
+    data App = App
+        { _routeFn :: AppUrl -> [(Text, Maybe Text)] -> Text
+        }
+
+    -- Thanks to the wonders of Generic, an empty instance
+    -- definition is all we need. Alternately, you can implement
+    -- toPathSegments and fromPathSegments yourself or use
+    -- web-routes-th.
+    instance PathInfo AppUrl
+
+    -- Set URL (Handler App App) to your URL data type defined above
+    -- and askRouteFn must point to the routing function you added to
+    -- your App.
+    instance MonadRoute (Handler App App) where
+       type URL (Handler App App) = AppUrl
+       askRouteFn = gets _routeFn
+
+### `Site.hs`
+
+Moving on to `Site.hs`, we'll setup handlers for each URL, as well initialise our app with a routing function.
+
+    -- Snap.Web.Routes provides routing functions
+    import Snap.Web.Routes
+
+    -- Add your new routes using routeWith
+    routes :: [(ByteString, Handler App App ())]
+    routes = [ ("", routeWith routeAppUrl)
+             , ("", serveDirectory "static")
+             ]
+
+    -- Define handlers for each value constructor in your URL data type.
+    routeAppUrl :: AppUrl -> Handler App App ()
+    routeAppUrl appUrl =
+        case appUrl of
+          (Count n)   -> writeText $ ("Count = " `T.append` (T.pack $ show n))
+          (Echo text) -> echo text
+          (Paths ps)  -> writeText $ T.intercalate " " ps
+
+    -- You'll note that these are normal Snap handlers, except they can take
+    -- values from the value constructor as arguments. This is a lot nicer than
+    -- having to use getParam.
+    echo :: T.Text -> Handler App App ()
+    echo msg = heistLocal (bindString "message" msg) $ render "echo"
+
+    -- Add the routing function to your app.
+    app :: SnapletInit App App
+    app = makeSnaplet "app" "An example snap-web-routes app." Nothing $ do
+        addRoutes routes
+        return $ App renderRoute
+
+If you prefixed the routes in routeWith (e.g. `("/prefix", routeWith routeAppUrl)`) then use `renderRouteWithPrefix` instead:
+
+    return . App $ renderRouteWithPrefix "/prefix"
+
+If you are having trouble figuring out why a particular request isn't routing as expected, try replacing `routeWith` with `routeWithDebug`. It'll display the available routes, as well as any failed route parses. Just remember that it's **not suitable for production** use.
+
+### Rendering URLs
+
+Helper functions are provided for rendering URLs:
+
+    echo :: T.Text -> Handler App App ()
+    echo msg = do
+        url <- showUrl $ Echo "this is a test"
+        if msg == "test" then redirect (encodeUtf8 url) else renderEcho
+      where
+        renderEcho = heistLocal (I.bindSplices echoSplices) $ render "echo"
+        echoSplices = do
+            "message"  ## I.textSplice msg
+            "countUrl" ## urlSplice (Count 10)
+
+In the example above you'll find we use `urlSplice` to turn a URL into a splice, and `showUrl` to render a URL as Text.
+
+
diff --git a/changelog b/changelog
--- a/changelog
+++ b/changelog
@@ -1,3 +1,12 @@
+2014-05-06 0.3.0.1
+
+* Move tutorial to readme as it didn't show up on Hackage
+
+2014-05-06 0.3.0.0
+
+* Rename heistUrl to urlSplice
+* Add convenience functions to render routes as Text
+
 2014-05-06 0.2.0.0
 
 * Document functions properly
diff --git a/snap-web-routes.cabal b/snap-web-routes.cabal
--- a/snap-web-routes.cabal
+++ b/snap-web-routes.cabal
@@ -1,10 +1,10 @@
 name:                snap-web-routes
-version:             0.3.0.0
+version:             0.3.0.1
 synopsis:            Type safe URLs for Snap
 description:
     Type safe URL generation and routing for Snap using web-routes.
     .
-    To get started, run through the tutorial in Snap.Web.Routes.
+    To get started, there is a __<https://github.com/lukerandall/snap-web-routes/blob/master/README.md tutorial on GitHub>__.
     .
     This builds on <https://github.com/stepcut/snap-web-routes-demo work>
     done by Jeremy Shaw. Thanks Jeremy!
diff --git a/src/Snap/Web/Routes.hs b/src/Snap/Web/Routes.hs
--- a/src/Snap/Web/Routes.hs
+++ b/src/Snap/Web/Routes.hs
@@ -1,102 +1,6 @@
 -- |
 -- This module provides a ready to use implementation of `web-routes` for Snap.
 --
--- The tutorial assumes you have a standard Snap app with an Application.hs and
--- Site.hs.
---
--- To get going, you'll need to add a few things to Application.hs
---
--- @
--- -- Enable a few extensions
---
--- \-\- Needed to derive a generic instance for our URL data type
--- \{\-\# LANGUAGE DeriveGeneric     \#\-\}
---
--- \-\- Needed by web-routes
--- \{\-\# LANGUAGE FlexibleInstances \#\-\}
--- \{\-\# LANGUAGE TypeFamilies      \#\-\}
---
--- \-\- Paths and params are of type Text.
--- import Data.Text (Text)
---
--- \-\- Snap.Web.Routes.Types exports everything you need to
--- \-\- define your PathInfo and MonadRoute instances.
--- import Snap.Web.Routes.Types
---
--- \-\- Your URL data type.  Deriving a `Generic` instance gives
--- \-\- you a `PathInfo` instance for free.
--- data AppUrl
---     = Count Int
---     | Echo Text
---     | Paths [Text]
---       deriving (Generic)
---
--- \-\- Extend your App type to include a routing function.
--- data App = App
---     { _routeFn :: AppUrl -> [(Text, Maybe Text)] -> Text
---     }
---
--- \-\- Thanks to the wonders of Generic, an empty instance
--- \-\- definition is all we need. Alternately, you can implement
--- \-\- toPathSegments and fromPathSegments yourself or use
--- \-\- web-routes-th.
--- instance PathInfo AppUrl
---
--- \-\- Set URL (Handler App App) to your URL data type defined above
--- \-\- and askRouteFn must point to the routing function you added to
--- \-\- your App.
--- instance MonadRoute (Handler App App) where
---    type URL (Handler App App) = AppUrl
---    askRouteFn = gets _routeFn
--- @
---
--- Moving on to Site.hs.
---
--- @
--- \-\- Snap.Web.Routes provides routing functions
--- import Snap.Web.Routes
---
--- \-\- Add your new routes using routeWith
--- routes :: [(ByteString, Handler App App ())]
--- routes = [ ("", routeWith routeAppUrl)
---          , ("", serveDirectory "static")
---          ]
---
--- \-\- Define handlers for each value constructor in your URL data type.
--- routeAppUrl :: AppUrl -> Handler App App ()
--- routeAppUrl appUrl =
---     case appUrl of
---       (Count n)   -> writeText $ ("Count = " `T.append` (T.pack $ show n))
---       (Echo text) -> echo text
---       (Paths ps)  -> writeText $ T.intercalate " " ps
---
--- \-\- You'll note that these are normal Snap handlers, except they can take
--- \-\- values from the value constructor as arguments. This is a lot nicer than
--- \-\- having to use getParam.
--- echo :: T.Text -> Handler App App ()
--- echo msg = heistLocal (bindString "message" msg) $ render "echo"
---
--- \-\- Add the routing function to your app.
--- app :: SnapletInit App App
--- app = makeSnaplet "app" "An example snap-web-routes app." Nothing $ do
---     addRoutes routes
---     return $ App renderRoute
--- @
---
--- If you prefixed the routes in routeWith
---
--- > ("/prefix", routeWith routeAppUrl)
---
--- then use `renderRouteWithPrefix` instead:
---
--- > return . App $ renderRouteWithPrefix "/prefix"
---
--- If you are having trouble figuring out why a particular request isn't routing
--- as expected, try replacing 'routeWith' with 'routeWithDebug'. It'll display
--- the available routes, as well as any failed route parses. Just remember that
--- it's not suitable for production use.
-
-
 module Snap.Web.Routes
   ( routeWith
   , routeWithDebug
